TL;DR
We shipped the same FSx for ONTAP audit logs to three backends simultaneously — Datadog, Grafana Cloud, and Honeycomb — without changing a single line of Lambda code. The OpenTelemetry Collector sits between our Lambda and the backends as a routing layer. Adding or removing a backend is a YAML config change, not a code deployment.
- Same audit logs → 3 backends simultaneously
- Zero Lambda code changes between backends (SHA-256 verified)
- OTel Collector as the vendor-neutral routing layer
- All 3 event sources work: FSx audit logs via S3 Access Point, EMS webhooks, FPolicy file operations
What We're Building
In Part 2, we built a Lambda that speaks Datadog's API directly. It works great — but what happens when your security team wants Splunk, your SRE team wants Grafana, and your platform team is evaluating Honeycomb?
You'd need three separate Lambdas, each with vendor-specific formatting, auth, and retry logic. That's vendor lock-in expressed as infrastructure.
The Problem: Vendor-Specific APIs = Lock-in
Every observability vendor has their own wire format:
| Vendor | Auth Header | Payload Format | Endpoint Pattern |
|---|---|---|---|
| Datadog | DD-API-KEY: <key> |
Custom JSON schema | https://http-intake.logs.{site}/api/v2/logs |
| Splunk | Authorization: Splunk <token> |
HEC event wrapper |
https://<host>:8088/services/collector/event |
| Grafana Cloud | Authorization: Basic <b64> |
OTLP | https://otlp-gateway-prod-<region>.grafana.net/otlp |
| Honeycomb | x-honeycomb-team: <key> |
OTLP | https://api.honeycomb.io |
If your Lambda speaks Datadog's API, switching to Grafana Cloud means rewriting your Lambda. That's the lock-in.
The Solution: OTLP as the Producer-to-Collector Contract
OpenTelemetry Protocol (OTLP) is the vendor-neutral producer-to-Collector contract. Our Lambda speaks OTLP — period. The OTel Collector handles routing, processing, and backend-specific export.
┌─────────────────────────────────────────────────────────────────────┐
│ AWS Account │
│ │
│ ┌──────────────┐ ┌──────────────────┐ ┌─────────────────┐ │
│ │ Audit Logs │────▶│ Lambda │ │ OTel Collector │ │
│ │ (via S3 AP) │────▶│ (OTLP Shipper) │────▶│ (Docker/Fargate)│ │
│ │ EMS/FPolicy │────▶│ │ │ │ │
│ └──────────────┘ └──────────────────┘ └─┬──────┬──────┬─┘ │
│ │ │ │ │
└──────────────────────────────────────────────────┼──────┼──────┼────┘
│ │ │
▼ ▼ ▼
Datadog Grafana Honeycomb
(AP1) Cloud
The Lambda sends OTLP/HTTP to the Collector. The Collector fans out to any combination of backends. Adding Honeycomb? Add 5 lines of YAML. Dropping Datadog? Remove 4 lines. No Lambda redeployment.
Prerequisites
Before starting, you need:
- FSx for ONTAP with audit logging configured (see Part 2 for setup)
- Docker installed locally (Colima works — see troubleshooting for compose compatibility)
-
At least one backend account:
- Datadog: API key + site (e.g.,
ap1.datadoghq.com) - Grafana Cloud: Instance ID + API token (Cloud Portal → OTLP)
- Honeycomb: Ingest API key (starts with
hcaik_)
- Datadog: API key + site (e.g.,
- AWS account with Lambda deployment capability
- Parts 1–4 context (recommended but not required — this integration works standalone)
FSx for ONTAP S3 Access Point note: The Lambda reads audit logs through an S3 Access Point attached to the FSx for ONTAP volume. Data remains on the FSx file system — it is not copied to a separate S3 bucket. S3 API throughput via FSx depends on the file system's provisioned throughput capacity, not standard S3 scaling. Validate FSx read throughput separately from Collector and backend ingest throughput.
The OTel Collector Configuration
The Collector config is the heart of this pattern. Here's the full verified configuration for multi-backend delivery:
# otel-collector-config.yaml
# ✅ VERIFIED WORKING (2026-05-18)
# Image: otel/opentelemetry-collector-contrib:0.152.0
# Backends: Grafana Cloud (ap-northeast-0) + Honeycomb
receivers:
otlp:
protocols:
http:
endpoint: 0.0.0.0:4318
processors:
# memory_limiter: # Recommended for production
# check_interval: 1s
# limit_mib: 512
# spike_limit_mib: 128
batch:
timeout: 5s
send_batch_size: 1000
exporters:
otlp_http/grafana:
endpoint: ${env:GRAFANA_OTLP_ENDPOINT}
headers:
Authorization: "Basic ${env:GRAFANA_BASIC_AUTH}"
otlp_http/honeycomb:
endpoint: https://api.honeycomb.io
headers:
x-honeycomb-team: ${env:HONEYCOMB_API_KEY}
x-honeycomb-dataset: ${env:HONEYCOMB_DATASET}
extensions:
health_check:
endpoint: 0.0.0.0:13133
service:
extensions: [health_check]
pipelines:
logs:
receivers: [otlp]
processors: [batch]
exporters: [otlp_http/grafana, otlp_http/honeycomb]
Depending on your Honeycomb environment and dataset model,
x-honeycomb-datasetmay be optional or handled differently. Refer to your Honeycomb OTLP setup page for the recommended configuration.This article uses
otlp_http(the forward-compatible component name). If your Collector version does not recognize it, use the olderotlphttpalias or upgrade the Collector.
Section Breakdown
| Section | Purpose | Key Settings |
|---|---|---|
receivers.otlp |
Accepts OTLP/HTTP from Lambda | Port 4318 (OTLP standard) |
processors.batch |
Buffers logs before export | 5s timeout OR 1000 records (whichever first) |
exporters.otlp_http/* |
Sends to each backend | Per-backend auth headers |
extensions.health_check |
Liveness probe | Port 13133 for curl -f checks |
service.pipelines |
Wires components together | logs: receiver → processor → exporters |
Production note: This configuration is suitable for development and validation. For production, add
retry_on_failureandsending_queuesettings to exporters, configurememory_limiterprocessor, and consider persistent storage extensions. Without persistent buffering, telemetry in the Collector's in-memory batch can be lost during Collector restarts.
Adding Datadog as a Third Backend
To send to all three simultaneously, add the Datadog exporter:
exporters:
# ... existing grafana + honeycomb exporters ...
datadog:
api:
key: ${env:DD_API_KEY}
site: ${env:DD_SITE}
service:
pipelines:
logs:
receivers: [otlp]
processors: [batch]
exporters: [otlp_http/grafana, otlp_http/honeycomb, datadog]
That's it. Restart the Collector. Same Lambda, same OTLP payload, now three destinations.
For Datadog, this example uses the Collector's dedicated
datadogexporter rather than genericotlp_http, because it handles Datadog-specific intake behavior, metadata mapping, and host tagging.
The Lambda Handler (OTLP Shipper)
Key Design Decisions
- Why OTLP? — It gives the Lambda a single producer-to-Collector contract. The Collector then handles each backend's supported exporter or intake path. One format to maintain, not three.
-
Why no vendor SDK? — SDKs add cold start latency, dependency management, and vendor coupling. Pure
urllib3+ JSON keeps the Lambda lean. -
Why AUTH_MODE? — Different Collectors may need different auth. The Lambda supports
none,basic, andbearermodes without code changes.
Field Mapping: FSx ONTAP → OTLP Attributes
The Lambda maps FSx ONTAP audit fields to semantic OTLP attribute keys:
| FSx ONTAP Field | OTLP Attribute Key | Example Value |
|---|---|---|
EventID |
event.type |
4663 |
UserName |
user.name |
admin@corp.local |
ClientIP |
client.address |
10.0.1.50 |
Operation |
fsxn.operation |
ReadData |
ObjectName |
fsxn.path |
/vol/data/reports/q4.xlsx |
Result |
fsxn.result |
Success |
SVMName |
fsxn.svm |
svm-prod-01 |
The examples above focus on S3 audit logs because they are the highest-volume path. The same OTLP shipper pattern is reused for EMS webhook events and FPolicy file operations using source-specific field mappers (
ems_handler.py,fpolicy_handler.py), while preserving the same Collector-facing OTLP contract. For EMS and FPolicy, source-specific service names are used (fsxn-ems,fsxn-fpolicy) to distinguish event sources in the backend.
Resource-level attributes (set once per payload, not per log record):
| Attribute | Value | Purpose |
|---|---|---|
service.name |
fsxn-audit |
Service identification |
cloud.provider |
aws |
Cloud context |
cloud.platform |
aws_fsx |
Platform context |
cloud.platform=aws_fsxis a project-specific value used to identify FSx for ONTAP as the data source. It is not part of the OpenTelemetry semantic conventions standardcloud.platformvalues (which includeaws_ec2,aws_ecs,aws_eks,aws_lambda, etc.).
Severity Determination Logic
The Lambda determines OTLP severity from the Result field:
WARN_KEYWORDS = ("fail", "denied", "error")
def determine_severity(result: Optional[str]) -> tuple[int, str]:
"""Determine OTLP severity from FSx ONTAP Result field."""
if not result:
return (9, "INFO")
lower = result.lower()
for keyword in WARN_KEYWORDS:
if keyword in lower:
return (13, "WARN")
return (9, "INFO")
This means failed access attempts (Result: "Failure") automatically get severityNumber: 13 (WARN), making them easy to filter in any backend.
The Lambda sets both severityNumber and severityText according to the OpenTelemetry Logs Data Model severity level definitions.
OTLP Payload Construction
def build_otlp_payload(
logs: list[dict[str, Any]],
service_name: str,
source_key: str,
) -> dict[str, Any]:
"""Build OTLP Log Data Model payload."""
log_records = [map_log_record(log) for log in logs]
return {
"resourceLogs": [{
"resource": {
"attributes": [
{"key": "service.name", "value": {"stringValue": service_name}},
{"key": "cloud.provider", "value": {"stringValue": "aws"}},
{"key": "cloud.platform", "value": {"stringValue": "aws_fsx"}},
]
},
"scopeLogs": [{
"scope": {"name": "fsxn-otel-shipper", "version": "1.0.0"},
"logRecords": log_records,
}],
}]
}
No vendor SDK. No vendor-specific formatting. Just the OTLP Log Data Model.
Retry with Exponential Backoff
MAX_RETRIES = 3
BASE_INTERVAL = 2 # seconds
def _send_otlp_payload(payload, endpoint, auth_headers=None) -> bool:
"""Send OTLP payload via HTTP POST with retry logic.
Retries on HTTP 429 and 5xx. Does not retry on 4xx (except 429).
Exponential backoff: 2s, 4s, 8s with jitter.
"""
url = f"{endpoint}/v1/logs"
headers = {"Content-Type": "application/json"}
if auth_headers:
headers.update(auth_headers)
json_body = json.dumps(payload).encode("utf-8")
for attempt in range(MAX_RETRIES):
response = http.request("POST", url, body=json_body, headers=headers, timeout=30.0)
if response.status < 300:
return True
if response.status == 429 or response.status >= 500:
wait_time = BASE_INTERVAL * (2 ** attempt) + random.uniform(0, 1)
time.sleep(wait_time)
continue
# Client error (4xx except 429) — don't retry
return False
return False
AUTH_MODE Support
The Lambda supports three authentication modes via the AUTH_MODE environment variable:
| AUTH_MODE | Behavior | Use Case |
|---|---|---|
none |
No auth headers sent | Local Collector (no auth needed) |
basic |
Authorization: Basic <base64(token)> |
Grafana Cloud direct |
bearer |
Authorization: Bearer <token> |
Generic OTLP endpoints |
When using the Collector pattern, set AUTH_MODE=none on the Lambda — the Collector handles backend auth via its own config.
Direct auth modes (
basic,bearer) are useful for testing or bypassing the Collector. In the multi-backend pattern, keepAUTH_MODE=noneand let the Collector handle backend credentials.
Deployment
Local Development: Docker Run
# 1. Configure credentials
cd integrations/otel-collector
cp .env.example .env
# Edit .env with your backend credentials:
# GRAFANA_OTLP_ENDPOINT=https://otlp-gateway-prod-ap-northeast-0.grafana.net/otlp
# GRAFANA_BASIC_AUTH=<base64(instanceId:apiToken)>
# HONEYCOMB_API_KEY=hcaik_<your-ingest-key>
# HONEYCOMB_DATASET=fsxn-audit
# 2. Start OTel Collector
docker run -d --name otel-collector \
-p 4318:4318 -p 13133:13133 \
-v $(pwd)/otel-collector-config.yaml:/etc/otelcol-contrib/config.yaml \
--env-file .env \
otel/opentelemetry-collector-contrib:0.152.0
# 3. Verify health
curl -f http://localhost:13133/
# Expected: HTTP 200 — {"status":"Server available", ...}
The
health_checkextension confirms the Collector process is available; it does not guarantee that each backend exporter is successfully delivering logs. Monitor exporter errors separately using the Collector's internal telemetry metrics if enabled and exposed.
# 4. Send a test payload
bash scripts/generate-otlp-payload.sh --output /tmp/payload.json
curl -X POST http://localhost:4318/v1/logs \
-H "Content-Type: application/json" \
-d @/tmp/payload.json
Colima users:
docker composev2 plugin is NOT available in Colima. All scripts in this repo detect this and fall back todocker run. If you see "docker compose: command not found", this is expected behavior.
First Success Path
If you're trying this for the first time, start small:
- Run the Collector locally with one backend.
- Send one fresh OTLP payload.
- Confirm the event appears in that backend.
- Add the second exporter.
- Only then move to multi-backend or AWS deployment.
This keeps the first validation focused on the producer-to-Collector contract before introducing backend parity and production networking.
AWS Deployment: CloudFormation
aws cloudformation deploy \
--template-file integrations/otel-collector/template.yaml \
--stack-name fsxn-otel-integration \
--parameter-overrides \
S3AccessPointArn=arn:aws:s3:ap-northeast-1:123456789012:accesspoint/fsxn-audit-ap \
OtlpEndpoint=http://<your-collector-endpoint>:4318 \
ApiKeySecretArn=arn:aws:secretsmanager:ap-northeast-1:123456789012:secret:fsxn-otel-key-XXXXXX \
AuthMode=none \
--capabilities CAPABILITY_IAM \
--region ap-northeast-1
This template deploys the Lambda-side OTLP shipper. The Collector endpoint must already be reachable from the Lambda — for example, a local Collector for development, an EC2-hosted Collector, or an ECS/Fargate-based Collector in the same VPC. If the Lambda is in a VPC, ensure security groups allow outbound TCP 4318 to the Collector. See the repository's VPC Deployment Guide and Security Hardening Guide for production Collector deployment.
When the Collector handles auth, set AuthMode=none on the Lambda. The Collector config contains the per-backend credentials via environment variables (sourced from .env or Secrets Manager in production).
Environment Variables
| Variable | Lambda | Collector | Description |
|---|---|---|---|
OTLP_ENDPOINT |
✅ | — | Collector URL (e.g., http://collector:4318) |
AUTH_MODE |
✅ | — |
none / basic / bearer
|
SERVICE_NAME |
✅ | — | OTLP service.name attribute |
GRAFANA_OTLP_ENDPOINT |
— | ✅ | Grafana Cloud OTLP gateway URL |
GRAFANA_BASIC_AUTH |
— | ✅ | base64(instanceId:apiToken) |
HONEYCOMB_API_KEY |
— | ✅ | Ingest key (hcaik_...) |
HONEYCOMB_DATASET |
— | ✅ | Dataset name |
DD_API_KEY |
— | ✅ | Datadog API key |
DD_SITE |
— | ✅ | Datadog site (datadoghq.com, datadoghq.eu, ap1.datadoghq.com, etc.) |
Verified Results
All backends were tested on 2026-05-18 using otel/opentelemetry-collector-contrib:0.152.0:
| Backend | Region/Site | Status | Event Sources | Auth Method |
|---|---|---|---|---|
| Datadog | ap1.datadoghq.com | ✅ Verified | S3 audit + EMS + FPolicy | Datadog exporter (DD-API-KEY) |
| Grafana Cloud | ap-northeast-0 | ✅ Verified | S3 audit + EMS + FPolicy | Basic Auth via otlp_http
|
| Honeycomb | — | ✅ Verified | S3 audit + EMS + FPolicy |
x-honeycomb-team via otlp_http
|
| Multi-Backend | Grafana + Honeycomb | ✅ Verified | Simultaneous delivery | Both auth methods |
| Multi-Backend | Datadog + Grafana + Honeycomb | ✅ Verified | Simultaneous 3-way delivery | All three exporters |
All three backends received the same structured attributes:
-
event.type,user.name,client.address -
fsxn.operation,fsxn.path,fsxn.result,fsxn.svm -
cloud.provider=aws,cloud.platform=aws_fsx
OTLP standardizes the producer-to-Collector contract, but backend-specific indexing, query semantics, and retention behavior still need to be validated per destination. OpenTelemetry is not a backend — it defines APIs, protocols, and Collector components for telemetry generation, collection, processing, and export. Storage, visualization, and alerting are handled by the backends themselves. See the Backend Parity Matrix and PoC Checklist for backend-specific validation details.
The Proof: Zero Code Changes
Here's the key evidence. The Lambda handler's SHA-256 hash is identical regardless of which backend receives the logs:
$ shasum -a 256 integrations/otel-collector/lambda/handler.py
# Same hash whether targeting Datadog, Grafana Cloud, or Honeycomb
# The file never changes — only the Collector config does
What changes between backends? Only the OTel Collector config file.
Demonstration: Adding a Backend
Starting state: Grafana Cloud only.
# Before: single backend
service:
pipelines:
logs:
exporters: [otlp_http/grafana]
Adding Honeycomb:
# After: add 5 lines to exporters section + update pipeline
exporters:
otlp_http/honeycomb:
endpoint: https://api.honeycomb.io
headers:
x-honeycomb-team: ${env:HONEYCOMB_API_KEY}
x-honeycomb-dataset: ${env:HONEYCOMB_DATASET}
service:
pipelines:
logs:
exporters: [otlp_http/grafana, otlp_http/honeycomb]
Restart the Collector. Done. No Lambda redeployment, no code review, no CI/CD pipeline for the shipper.
Demonstration: Removing a Backend
Dropping Datadog during a migration to Grafana Cloud:
# Remove from exporters list — that's it
service:
pipelines:
logs:
exporters: [otlp_http/grafana] # removed: datadog
Troubleshooting
Timestamp Rejection / Static Payload Gotcha
Datadog documents that logs older than 18 hours are dropped at intake (Datadog Logs API docs). Other backends may also reject or hide events with timestamps outside their accepted windows. In my testing, future timestamps also caused ingestion issues on some backends. When testing with static payloads, always generate fresh timestamps.
Fix: Use the payload generator to create fresh timestamps:
bash scripts/generate-otlp-payload.sh --output /tmp/fresh-payload.json
curl -X POST http://localhost:4318/v1/logs \
-H "Content-Type: application/json" \
-d @/tmp/fresh-payload.json
Grafana Cloud Auth Format
The loki exporter is NOT the correct approach for OTLP → Grafana Cloud.
- ❌
lokiexporter with Loki push API - ✅
otlp_http/grafanawith OTLP gateway endpoint
The Basic Auth value must be base64(instanceId:apiToken):
# Generate the auth value
echo -n "<your-instance-id>:<your-grafana-cloud-api-token>" | base64
Where the instance ID is your numeric Grafana Cloud instance ID (found in Cloud Portal → OTLP configuration).
Honeycomb Key Types
Honeycomb has two key types. Only ingest keys work for data ingestion:
| Key Prefix | Type | Works for OTLP? |
|---|---|---|
hcaik_ |
Ingest API key | ✅ Yes |
hcxik_ |
Environment key | ❌ No |
If you see 401 Unauthorized from Honeycomb, check your key prefix.
Colima Docker Compose Compatibility
docker compose v2 plugin is not available in Colima environments. All scripts in this repository detect this automatically and fall back to docker run. This is expected — not an error.
If you need compose-like orchestration on Colima, use the explicit docker run commands shown in the Deployment section.
Common Mistake: loki Exporter vs otlp_http
A frequent misconfiguration when targeting Grafana Cloud:
# ❌ WRONG — loki exporter uses Loki-specific push API
exporters:
loki:
endpoint: https://logs-prod-<region>.grafana.net/loki/api/v1/push
# ✅ CORRECT — otlp_http uses the OTLP gateway
exporters:
otlp_http/grafana:
endpoint: https://otlp-gateway-prod-<region>.grafana.net/otlp
The OTLP gateway is Grafana Cloud's native OTLP ingestion endpoint. It handles logs, metrics, and traces through a single URL.
Cost Model: How to Think About It
Lambda Cost (OTLP Path vs Direct Send)
In my validation, the OTLP Lambda was simpler and shorter-lived than the vendor-specific direct-send path. Your duration will vary depending on batching, payload size, network path, and backend response time.
| Component | Direct Send (Part 2) | OTLP + Collector |
|---|---|---|
| Lambda complexity | Vendor formatting + HTTP + retry | OTLP POST to nearby Collector |
| Lambda memory | 256MB | 256MB |
| Vendor SDK deps | Yes (adds cold start) | None |
| Retry complexity | Per-vendor | Delegated to Collector |
OTel Collector Cost
The Collector introduces a fixed infrastructure cost that is independent of event volume:
| Deployment | Best For |
|---|---|
| Docker on local machine | Development, testing |
| Docker on EC2 Spot (t3.small) | Low-volume production |
| ECS Fargate (0.5 vCPU, 1GB) | Production (no OS management) |
| ECS Fargate + NAT Gateway | VPC-internal production |
When to Use Each Pattern
| Scenario | Recommendation |
|---|---|
| Single vendor, low volume | Direct Send (Part 2 pattern) — no Collector overhead |
| Single vendor, high volume | Collector (buffering + backpressure benefits) |
| Multi-vendor evaluation | Collector (add/remove exporters freely) |
| Vendor migration in progress | Collector (parallel delivery during cutover) |
| Compliance: logs in multiple systems | Collector (fan-out is a config change) |
The Collector has fixed infrastructure costs regardless of volume. As volume increases or vendors multiply, the Collector path becomes more cost-effective because it processes once and fans out. The Collector path centralizes fan-out outside the Lambda. Direct-send can also fan out within one Lambda, but that pushes vendor-specific formatting, retry behavior, and failure isolation back into application code.
Important: Backend ingest/retention costs are not included in these AWS-side estimates. Datadog, Grafana Cloud, and Honeycomb each have their own pricing models that can become the dominant cost at scale.
When to Use This Pattern
Multi-Vendor Evaluation
Want to try Honeycomb for a month alongside your existing Datadog setup? Add one exporter to the Collector config. No Lambda redeployment. No risk to your existing pipeline.
Compliance: Logs in Multiple Systems
Some organizations require audit logs in multiple systems — security team uses Splunk, dev team uses Datadog, compliance team needs a cold archive. The Collector fans out to all simultaneously from a single OTLP stream.
Migration Between Vendors
Moving from Datadog to Grafana Cloud? Run both exporters in parallel during migration. Verify data parity in the new system. Remove the old exporter when satisfied. Zero-downtime vendor migration.
Cost Optimization: Route by Volume
Use the Collector's processor pipeline to route high-volume noisy logs (read operations) to a cheaper backend while keeping security-critical events (deletes, permission changes) on a premium platform with alerting.
What's Next
For production hardening, the repository includes guides covering VPC deployment, health monitoring, persistent buffering, security hardening, and benchmarking. Auto-scaling and Multi-AZ deployment are natural next steps for production Collector operations.
For production and partner-led deployments, the repository includes:
- Architecture Decision Record
- VPC Deployment Guide — private networking, security groups, and Collector reachability from Lambda
- Config Governance Guide
- Security Hardening Guide
- Operations Guide
- Cost Model
- PoC Checklist
- Routing and Filtering Examples
- Compliance Evidence Note
- Migration Guide — zero-downtime migration from direct-send to the Collector path
- OTel Semantic Mapping Guide — standard vs project-specific attributes, schema evolution, and what OTLP does not solve
- Backend Parity Matrix — visibility and query behavior across Datadog, Grafana Cloud, and Honeycomb
- Glossary / 用語集 — English/Japanese OTel terminology used in this project
- Enterprise Workload Addendum — SAP, VMware, and mission-critical workload considerations
- Storage Service Selection Note — when to use FSx for ONTAP, Amazon S3, Amazon EFS, and Amazon EBS
Key Takeaways
- OTLP is the stable producer contract. Your Lambda speaks one protocol; the Collector handles backend-specific exporters.
- OTel Collector is the routing and processing layer that decouples log producers from observability backends.
- Zero Lambda code changes when switching or adding backends — verified with SHA-256 hash comparison.
- Multi-backend delivery is a config change, not a code change. Add 5 lines of YAML, restart the Collector.
- All three FSx ONTAP event sources work: FSx audit logs via S3 Access Point (Part 2), EMS webhooks (Part 3), and FPolicy file operations (Part 4).
- Collector economics improve as volume increases or vendors multiply — fixed Collector cost is amortized across all destinations.
- Start with direct send (Part 2) for simplicity. Graduate to the Collector when you need multi-backend, vendor migration, or volume-based routing.
Series Navigation
- Part 1: Why Your FSx for ONTAP Logs Deserve Better
- Part 2: Shipping FSx for ONTAP Logs to Datadog — The Serverless Way
- Part 3: Event-Driven Ransomware Detection with ONTAP ARP + Datadog
- Part 4: FPolicy File Activity Pipeline — ONTAP to Datadog via ECS Fargate
- Part 5: Escape Vendor Lock-in with OTel Collector (this post)
Questions about the OTel Collector pattern or multi-backend delivery? Drop a comment below.
Previous: Part 4 — FPolicy File Activity Pipeline
GitHub: github.com/Yoshiki0705/fsxn-observability-integrations
Top comments (0)