-
Notifications
You must be signed in to change notification settings - Fork 31
Logging to OpenTelemetry
Starting with RFLIB 11.0.0, log events can be forwarded to any OpenTelemetry Protocol (OTLP) logs endpoint that accepts OTLP/HTTP JSON. The single Send_Log_Event_to_OTel action (rflib_OpenTelemetryLogAction) emits OTLP/HTTP JSON (Content-Type: application/json) and works with:
- AWS CloudWatch Logs native OTLP endpoint β accepts OTLP/HTTP JSON; a serverless, Lambda-free alternative to the API Gateway + Lambda setup in Logging to AWS CloudWatch.
- OpenTelemetry Collectors and any backend reachable through one (Grafana/Tempo/Loki, Datadog, Honeycomb, New Relic, Splunk, β¦).
- Azure Monitor β only via an OpenTelemetry Collector in between (see the Azure recipe below). Azure Monitor's native OTLP ingestion requires OTLP/HTTP protobuf, which this action does not emit. For direct Azure ingestion without a collector, use the App Insights action instead β see Logging to Azure App Insights.
Encoding note: this action emits OTLP/HTTP JSON, not protobuf (Apex has no practical protobuf serializer). Any backend you target must accept the JSON encoding (or sit behind a collector that does).
The destination URL and any backend-specific headers (API keys, log-group names, etc.) live entirely on the RFLIB_OTEL_LOGS Named Credential, so switching or adding a backend never requires a code change.
Each batch of log events becomes a single OTLP resourceLogs payload. Every event is one logRecord:
-
timeUnixNano/observedTimeUnixNanoβ the event's created timestamp in nanoseconds -
severityNumber/severityTextβ the RFLIB level mapped to the OTel severity scale (see below) -
body.stringValueβ the log messages (front-truncated to keep the most recent content) -
attributesβrflib.context,rflib.request_id,rflib.source_system_id,rflib.log_source,rflib.stacktrace,enduser.id, plus the event'sPlatform_Info__cflattened into typed attributes (rflib.apex.*,rflib.browser.*,user_agent.original)
Resource attributes identify the source: service.name (the OTel_Service_Name Global Setting, default salesforce-rflib), service.instance.id (the Org Id), and telemetry.sdk.name / telemetry.sdk.language / telemetry.sdk.version (rflib-apex / apex / the package version).
RFLIB's request id is carried as the
rflib.request_idattribute rather than the OTLPtraceId/spanIdfields, because those require 16-/8-byte hex identifiers that the Salesforce request id does not satisfy. RFLIB forwards fire-and-forget and does not implement OTLP throttling /Retry-Afterbackoff; rejected or failed sends are recorded asrflib-otel-log-event-failedapplication events.
Events are sent in callouts of up to 100 records, and each request body is also capped at ~1,000,000 bytes so it stays within the strictest documented OTLP/HTTP vendor limit (e.g. New Relic caps payloads at 1,000,000 bytes); larger volumes are split across multiple callouts. Backends that accept bigger payloads still work, and for very high volume an OpenTelemetry collector in front of RFLIB is recommended. Any 2xx response with no partialSuccess.rejectedLogRecords is treated as success (collectors typically return 200, gateways such as Grafana Cloud return 204 No Content); anything else is recorded as an rflib-otel-log-event-failed application event with the response body for diagnosis. RFLIB does not retry (fire-and-forget).
| RFLIB level | OTel severityNumber
|
severityText |
|---|---|---|
| TRACE | 1 | TRACE |
| DEBUG | 5 | DEBUG |
| INFO | 9 | INFO |
| WARN | 13 | WARN |
| ERROR | 17 | ERROR |
| FATAL | 21 | FATAL |
-
Install RFLIB 11.0.0 or later.
-
Create a Named Credential named exactly
RFLIB_OTEL_LOGSwhose URL is the full OTLP logs endpoint (including the/v1/logspath or the backend's equivalent). Configure authentication and any required custom headers per the recipe below. -
(Optional) Create an RFLIB Global Setting
OTel_Service_Nameto override the defaultservice.nameofsalesforce-rflib. See Global Config Settings. -
In Logger Settings, set OTel Log Level to
ERROR(or higher-verbosity as needed). It must be at or above the Log Event Reporting Level. Default isNONE(disabled). See Logger Settings. -
Validate with anonymous Apex:
rflib_Logger logger = rflib_LoggerUtil.getFactory().createLogger('OTelTest'); logger.setReportingLogLevel(rflib_LogLevel.ERROR); logger.error('RFLIB β OTLP connectivity test');
Failures appear as
rflib-otel-log-event-failedapplication events.
The running user (or the Automated Process / Default Workflow user, depending on how the RFLIB Log Event Handler flow runs) must have principal access to the External Credential behind
RFLIB_OTEL_LOGS. Without it, callouts fail with 401/403.
Azure Monitor's native OTLP ingestion accepts only OTLP/HTTP protobuf, so RFLIB cannot post to the DCR endpoint directly (it emits JSON). Two options:
-
Recommended for Azure: skip OTLP and use the App Insights action (
RFLIB_APP_INSIGHTS), which ingests directly over JSON. See Logging to Azure App Insights. -
If you specifically want the OTLP pipeline: run an OpenTelemetry Collector that accepts OTLP/HTTP JSON from Salesforce and re-exports OTLP/HTTP protobuf to Azure Monitor. Point
RFLIB_OTEL_LOGSat the collector's/v1/logs(not the DCR), and configure the collector with the Azure auth + DCR endpoint per Microsoft's collector docs. Flow:Salesforce β (OTLP/JSON) β Collector β (OTLP/protobuf) β Azure Monitor.
CloudWatch Logs exposes a native OTLP endpoint, so you can drop the API Gateway + Lambda pipeline entirely.
- External Credential: AWS Signature Version 4 (the same pattern as the existing CloudWatch wiki), service
logs, with an IAM identity allowed tologs:PutLogEvents. - Named Credential URL:
https://logs.<region>.amazonaws.com/v1/logs - Add custom headers on the Named Credential:
x-aws-log-group: <your-log-group>x-aws-log-stream: <your-log-stream>
CloudWatch also reports dropped records via partialSuccess.rejectedLogRecords, which RFLIB surfaces as an application event.
- Named Credential URL: your collector or vendor endpoint ending in
/v1/logs. - Add whatever auth the backend expects (e.g. an
Authorizationor API-key custom header) on the Named Credential.
| Symptom | Likely cause |
|---|---|
rflib-otel-log-event-failed with 401/403 |
Wrong/missing auth on the Named Credential, or the flow's running user lacks External Credential principal access. |
| 200 but recorded as failure |
partialSuccess.rejectedLogRecords > 0 β inspect the app event body for the per-record reasons (e.g. timestamps too old/new for CloudWatch). |
| Nothing arrives, no app events |
OTel_Log_Level__c is NONE or below the Log Event Reporting Level. |
| Records rejected as "too old" (CloudWatch) | CloudWatch rejects events older than 14 days / newer than 2 hours. |
- Logging to Azure App Insights β direct Azure ingestion without a collector
- Logging to AWS CloudWatch β the API Gateway + Lambda pipeline
- 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