-
Notifications
You must be signed in to change notification settings - Fork 31
Logging to Azure App Insights
Starting with RFLIB 11.0.0, log events can be forwarded to Azure Application Insights so that Salesforce logs are searchable alongside the rest of your Azure observability data. The integration sends telemetry directly from Apex to the Application Insights ingestion endpoint — there is no Azure Function, App Gateway, or other compute to deploy or pay for. The only ongoing Azure charge is Log Analytics ingestion (pay-per-GB), which a daily cap keeps under control.
There are two ways to land RFLIB logs in Azure:
| Route | Action | Status | Where logs land |
|---|---|---|---|
| A. App Insights direct ingestion (recommended) |
Send_Log_Event_to_App_Insights (rflib_AppInsightsLogAction) |
GA | App Insights traces table |
| B. Azure Monitor OTLP ingestion (via a Collector) |
Send_Log_Event_to_OTel (rflib_OpenTelemetryLogAction) |
Preview | Log Analytics (OTel schema) |
Route A is documented in full below. Route B is summarized at the end and shares the generic OpenTelemetry setup in Logging to OpenTelemetry.
rflib_Log_Event__e ──► RFLIB Log Event Handler (Flow) ──► rflib_AppInsightsLogAction
│ POST (NDJSON envelopes)
▼
Named Credential RFLIB_APP_INSIGHTS (Entra OAuth)
│
▼
Application Insights ingestion endpoint (v2.1/track)
│
▼
App Insights `traces` (Log Analytics workspace)
Each log event becomes a Microsoft.ApplicationInsights.Message envelope. The RFLIB log level maps to the App Insights severity scale, and the event's Platform_Info__c is flattened into individually queryable custom properties (e.g. rflib.apex.cpu_time, user_agent.original).
- Compute: none. Ingestion is a direct HTTPS call from Salesforce.
- Ingestion: Log Analytics charges per GB ingested. The provided Bicep template sets a 1 GB/day cap and 30-day retention (retention up to 31 days is included at no charge).
- Keep the
App_Insights_Log_Level__cthreshold atERRORorWARNin production to limit volume.DEBUG/TRACEcan generate significant data.
- An Azure subscription and permission to create resources and Entra app registrations.
- The Azure CLI (
az) — the Azure Cloud Shell has everything pre-installed. - RFLIB 11.0.0 or later installed in your Salesforce org.
The Bicep template and helper scripts referenced below ship in the repository under azure/.
az group create -n rflib-logging -l eastus
az deployment group create -g rflib-logging -f azure/bicep/rflib-app-insights.bicepRecord the deployment outputs:
-
appInsightsResourceId— used for the role assignment in Step 2. -
instrumentationKey— used for the Global Setting in Step 5. -
connectionString— contains theIngestionEndpoint(e.g.https://eastus-8.in.applicationinsights.azure.com/) used for the Named Credential in Step 4.
bash azure/scripts/setup-entra-app.sh <appInsightsResourceId>The script creates an app registration + service principal, generates a client secret, assigns the least-privilege Monitoring Metrics Publisher role on the resource, and prints the values you need for Salesforce: Tenant ID, Client ID, Client Secret, Token Endpoint, OAuth Scope.
Role assignments can take a few minutes to propagate. If your first callout returns 403, wait and retry.
In Setup → Security → Named Credentials → External Credentials, create one named RFLIB_APP_INSIGHTS_AUTH:
- Authentication Protocol: OAuth 2.0
- Authentication Flow Type: Client Credentials with Client Secret
-
Identity Provider URL / Token Endpoint:
https://login.microsoftonline.com/<tenantId>/oauth2/v2.0/token -
Scope:
https://monitor.azure.com//.default(the double slash is intentional — the audience ishttps://monitor.azure.com/) - Add a Principal (Named Principal) and enter the Client ID and Client Secret from Step 2.
In Setup → Named Credentials, create one named exactly RFLIB_APP_INSIGHTS:
-
URL: the
IngestionEndpointfrom the connection string (e.g.https://eastus-8.in.applicationinsights.azure.com) -
External Credential:
RFLIB_APP_INSIGHTS_AUTH - Generate Authorization Header: enabled
Most common setup failure: the Log Event Handler flow runs as the Automated Process / Default Workflow user, not you. That user must have principal access to the External Credential, otherwise callouts fail with 401 and are recorded as
rflib-app-insights-log-event-failedapplication events. Create a Permission Set that grants access to theRFLIB_APP_INSIGHTS_AUTHprincipal and assign it to the user the flow runs as.
Create an RFLIB Global Setting so each telemetry envelope is routed to your resource. In Setup → Custom Metadata Types → RFLIB Global Setting → Manage Records, create a record:
-
Name / DeveloperName:
App_Insights_Instrumentation_Key -
Value: the
instrumentationKeyfrom Step 1
See Global Config Settings for the full Global Setting reference.
In Setup → Custom Settings → Logger Settings → Manage, set App Insights Log Level to ERROR (or WARN/INFO/…). The level must be the same or higher than the Log Event Reporting Level, otherwise the events are never published in the first place. The default is NONE, which disables forwarding. See Logger Settings.
Run anonymous Apex to emit an error log event:
rflib_Logger logger = rflib_LoggerUtil.getFactory().createLogger('AppInsightsTest');
logger.setReportingLogLevel(rflib_LogLevel.ERROR);
logger.error('RFLIB → Application Insights connectivity test');After 1–3 minutes, query in the Application Insights Logs blade:
traces
| where message has "connectivity test"
| project timestamp, message, severityLevel, customDimensions
| order by timestamp descThe customDimensions will include Context, RequestId, LogLevel, and the flattened rflib.apex.* platform-info values.
| Symptom | Likely cause |
|---|---|
rflib-app-insights-log-event-failed app events with 401 |
The flow's running user lacks principal access to RFLIB_APP_INSIGHTS_AUTH (see Step 4 note). |
| 403 on first callouts | Role assignment still propagating, or the wrong scope. |
| HTTP 206 recorded as failure | Partial success — some items were rejected. The app event body contains itemsReceived/itemsAccepted/errors[]. RFLIB does not retry. |
| Nothing arrives, no app events |
App_Insights_Log_Level__c is NONE or below the Log Event Reporting Level; or the App_Insights_Instrumentation_Key Global Setting is missing (forwarding is skipped when blank). |
| Daily data missing | The Log Analytics daily cap was reached — raise dailyCapGb or the log-level threshold. |
If you prefer the vendor-neutral OpenTelemetry pipeline, note an important constraint: Azure Monitor's native OTLP ingestion accepts only OTLP/HTTP protobuf, while RFLIB's rflib_OpenTelemetryLogAction emits OTLP/HTTP JSON (Apex has no practical protobuf serializer). RFLIB therefore cannot post to the Azure DCR endpoint directly.
To use this route, run an OpenTelemetry Collector between Salesforce and Azure Monitor:
- Create an Application Insights resource with OTLP support: On (auto-provisions the Data Collection Endpoint/Rule) and assign Monitoring Metrics Publisher on the DCR to the app registration.
- Deploy an OpenTelemetry Collector that accepts OTLP/HTTP JSON and exports OTLP/HTTP protobuf to the Azure DCR endpoint (
https://<dce>.<region>.ingest.monitor.azure.com/dataCollectionRules/<dcr-immutable-id>/streams/Microsoft-OTLP-Logs/otlp/v1/logs) using the Azure auth extension. - Point the
RFLIB_OTEL_LOGSNamed Credential at the collector's/v1/logsendpoint and setOTel_Log_Level__cin the Logger Settings.
Flow: Salesforce → (OTLP/JSON) → Collector → (OTLP/protobuf) → Azure Monitor. Logs land in Log Analytics using the OpenTelemetry schema. See Logging to OpenTelemetry for the collector recipe and other OTLP backends.
For direct Azure ingestion without a collector, use Route A (App Insights direct ingestion) above — it is the recommended path for most Azure users. This OTLP ingestion path is also in public preview at the time of writing.
- Logging to OpenTelemetry — the vendor-neutral OTLP forwarder
- Logging to AWS CloudWatch
- Logger Settings and Global Config Settings
- Home - Start here for installation and learning path
- Getting Started with Logging - Start here
- Logger Settings - Configure your logging
- Getting Started with Feature Switches - Control features
- Getting Started with Application Events - Track business metrics
- Getting Started with Logging - Core logging guide
- Logger Settings - Detailed configuration
- Log Archive - Long-term storage
- Using Log Aggregation - Trend analysis
- Using the Log Timer - Performance tracking
- Masking Log Messages - Security & privacy
- Logging in OmniStudio - OmniStudio integration
- RFLIB CLI Plugin - Automation tools
- Ops Center Overview - Central monitoring hub
- Logging Dashboard - View and analyze logs
- Management Console - System administration
- Permissions Explorer - Security validation
- Application Event Dashboard - Business insights
- Getting Started with the Trigger Framework - Metadata-driven triggers
- Getting Started with Retryable Actions - Reliable async processing
- Getting Started with HTTP Mocking - Integration testing
- Node / LWR Logger - Server-side Node.js / LWR logging
- Salesforce Functions - Serverless compute (EOL — see Node / LWR Logger)
- Logging to AWS CloudWatch - Cloud monitoring
- Logging to Azure App Insights - Azure observability
- Logging to OpenTelemetry - OTLP/HTTP forwarding
- Logging to Slack - Slack integrations
- Logging to Microsoft Teams - Teams integrations
- Logging to Google Chat - Google Chat integrations
- Getting Started with Pharos - External analytics
- [Outbound Callouts including the T