Integration · IT and security
How to build SaaS security log collection
The investigation needs last Tuesday's sign-ins from the HR system, and the feed stopped in March. The design behind log collection that notices when it goes quiet, the prompts that build it, and what running it takes.
Built with Tray Headless
- System Okta
- Step Pull on a schedule
- Step Map to one shape
- Step Watch for silence
- System Splunk
Every source has an expected rhythm, so a feed that goes quiet raises an alert instead of leaving a gap nobody finds until an investigation needs it.
The short answer
What is SaaS security log collection?
SaaS security log collection has four parts: an inventory of which apps matter and which of their events detections need, collection that pulls each app's events on a schedule and picks up where it left off, mapping every event to one shape so a sign-in looks the same whichever app it came from, and a watch on each feed that alerts when it goes quiet. The part teams skip is the watch. A feed that stops sends no error, so the gap is found months later, by the investigation that needed it.
Stage 1 of 7: Security log collection. Part of Security operations, end to end : every stage, the systems it runs on and the guide that builds it.
What matters here
- Start from the detections you want, not from every log an app can produce. Volume costs money and hides the events that matter.
- Pull from where the last run stopped, not from a fixed window. A fixed window drops events whenever a run is late.
- Map every event to one shape. A sign-in should look the same in the SIEM whether it came from Okta, Google Workspace or GitHub.
- Watch every feed for silence. A feed that stops sends no error, and nothing else will tell you.
- Keep the raw event next to the mapped one. An investigation always needs a field the mapping dropped.
Who this is for
You run security operations or detection engineering. Your company runs on dozens of SaaS apps, and the SIEM sees a fraction of what they record.
How it works in practice
From an event happening in an app to it being searchable next to everything else.
- 1
Each app is listed with the events detections need
Sign-ins, admin changes, permission grants, data exports and API token creation, per app, with an owner.
- 2
Events are pulled on a schedule from where the last run stopped
So a late or failed run catches up rather than leaving a gap.
- 3
Every event is mapped to one shape
Who, what, when, from where, on which app, with the raw event kept alongside.
- 4
Events land in the SIEM within minutes
Batched for cost, but never held long enough to slow a detection.
- 5
Each feed is watched for silence
An app that normally sends events every few minutes and has sent none for an hour raises an alert.
- 6
Coverage is reported
Which apps feed the SIEM, how late each feed runs, and which apps still don't feed it at all.
What log collection is made of
Four parts, and the last one is the one that decides whether the other three can be trusted.
A source inventory
Which apps hold sensitive data or admin power, and which of their events a detection or investigation needs. The list is the scope.
Collection that resumes
Each run starts where the last one stopped and records where it reached. Late runs catch up, and nothing is pulled twice.
One shape for every event
Actor, action, target, time, source address and app, in the same fields for every source, plus the raw event.
A watch on every feed
Each source has an expected rhythm. Silence beyond it is an alert with an owner, not a gap found later.
The Tray Headless prompts
Paste these into Claude Code or Codex with the Tray Headless plugin installed. Each stage runs on its own. The systems named in them are the worked example rather than a requirement, and every prompt says so.
Once per project, run
/tray-workflows:set-workspace
to pick the workspace these build in. Point it at a sandbox first.
- 1
Set up, then build the source inventory
Collecting everything costs money and buries the events that matter.
Headless skills
build-workflowUse build-workflow. The systems in play are Okta, Office365 Management, Google Workspace, GitHub, Splunk HTTP Event Collector, Slack and AWS S3, or whatever we run in those seats. Before you plan anything, tell me which of them are already authenticated in the workspace, because I do not want a connector stubbed that I have not authenticated. Start with the inventory, not the pipes. For each app list: what sensitive data or admin power it holds, which of its events a detection or investigation needs (sign-ins, admin changes, permission grants, data exports, new API tokens), how it exposes them, and who owns the app. Mark the apps that hold sensitive data but expose no events at all. That list is worth knowing before anybody claims coverage.
- 2
Pull each source from where the last run stopped
A fixed time window drops events every time a run is late.
Headless skills
build-workflowUse build-workflow. For each source, build a scheduled pull that: Reads the position where the last successful run stopped Requests events from that position, page by page Records the new position only after the events have landed Catches up in order if a run was missed or failed Respect each app's rate limits and slow down when it asks. Some apps only keep events for a few days, so a feed that falls behind by more than that loses them for good. Alert well before that point. Never use "the last fifteen minutes" as the window. A run that starts late by two minutes drops two minutes of events, every time.
- 3
Map every event to one shape, and keep the raw
A sign-in should look the same whichever app it came from.
Map every event to the same fields: Actor: user, email, and whether it is a person or a service account Action: sign-in, failed sign-in, admin change, permission grant, export, token created Target: what was acted on Time in UTC, source address, user agent, and app Send the mapped event to the SIEM with the raw event attached. Every investigation eventually needs a field the mapping dropped, and the raw event is the only place it still exists. Keep a copy in cheap storage for as long as policy says. Most SIEMs keep data for months, and an investigation sometimes needs a year.
- 4
Watch every feed for silence
A feed that stops sends no error.
Headless skills
tray-gotchasUse tray-gotchas, then learn each source's normal rhythm from two weeks of data: how many events per hour, by hour of day and day of week. Alert the source owner in Slack when a feed is silent well beyond its rhythm, when its volume drops sharply, or when a run has failed several times in a row. Include when the last event arrived and what the last error was. A quiet weekend is normal for some apps and a sign of trouble for others. Learn the rhythm per source rather than setting one threshold for all of them.
The silence check is the control. Everything else is plumbing, and plumbing fails without telling anyone.
- 5
Report coverage honestly
Coverage is a claim auditors and the board will test.
Report weekly: which apps feed the SIEM, how far behind each feed runs, which feeds went quiet and for how long, and which apps in the inventory still don't feed it. Count an app as covered only if its events arrived in the last hour and its last silence was resolved. An app connected once and broken since is not covered.
- 6
Validate it, then hand the inventory to security ops
Because the list of apps changes every time somebody buys one.
Run the per-step schema checks and the whole-workflow audit before this touches production. Run it alongside any existing feeds for a week and compare event counts per source, so a gap shows up before the old feed is turned off. Then open the same workflow in Tray Build so security operations can add sources, change the mapping and tune the silence thresholds in the visual canvas.
What it connects to
The events live in each app, and the SIEM needs them in one shape and on time.
GitHub
Read organization audit events: permission changes, new tokens, repository visibility changes.
Reads
Splunk HTTP Event Collector
Send each mapped event, with its raw original attached, into the SIEM.
Writes
Slack
Tell a source's owner when its feed goes quiet, with the last event time and the last error.
Writes
Same build, other stacks
The design does not change if you run something else in one of these seats. The same prompts build it against Microsoft Teams, Azure Active Directory or Google Chat.
Connections in this build
Field mapping, templates and common problems for each pairing: Office365 Management + Okta, G-Suite + Okta, Office365 Management + Splunk HTTP Event Collector and Okta + Slack.
Named systems are the ones most teams run, not the only ones that work. Each is an authentication in your Tray workspace, referenced by name, so the workflow never holds a credential. Where we have a connector page, the name links to it.
Running it in production
This decides what the SIEM can see. A gap here is a gap in every detection that relies on it.
It runs where production runs, not on a laptop
Every source is pulled on schedule, around the clock, with each run and its position recorded.
Every feed has an owner and a rhythm
Silence beyond the rhythm is an alert to a named person, so a broken feed is a ticket, not a surprise.
Managed credentials, not secrets in a config file
Read access to every app's audit log is powerful. Each is a scoped, read-only authentication in your workspace, rotated on its own.
Security ops own the sources
Sources, mapping and silence thresholds open in Tray Build, owned by the team that relies on the data.
Run it alongside the old feed first
A week of both, with event counts compared per source, before anything is turned off.
Questions people ask
Why not collect every log an app produces?
Because volume costs money and buries the events detections need. Start from the detections and investigations you want, and collect what they use.
Why pull from where the last run stopped?
Because a fixed window drops events whenever a run is late. Recording the position after each successful run means a late or failed run catches up instead.
Why keep the raw event?
Because every investigation eventually needs a field the mapping dropped. The raw event is the only place it still exists.
How do you know a feed has stopped?
By learning each source's normal rhythm and alerting when it goes quiet beyond it. A stopped feed sends no error, so silence is the only signal.
What counts as a covered app?
An app whose events arrived in the last hour and whose last silence was resolved. An app connected once and broken since does not count.
Related guides
IT and security
How to build security alert triage
Enrich before a human sees it, suppress the known-benign, escalate on asset value, and measure what you closed rather than what fired. The prompts.
IT and security
How to build compromised account response
Ask the user about a risky sign-in, revoke every session in every app on a confirmed takeover, and remove what the attacker left behind. The prompts.
Data operations
How to build data quality monitoring
Test what breaks decisions, alert the owner rather than a channel, and say what depends on a failure. The Headless prompts that build it.
Last reviewed October 2026.