perf(slack): dedupe webhook JSON.parse + LOG_LEVEL=debug perf timings#443
Merged
Conversation
…ings
(A) JSON.parse dedup
verifySlackRequest used to JSON.parse(rawBody) a second time to derive
the payload it returned. The router already parses rawBody once before
calling it, so the same body was deserialized twice per webhook.
Change verifySlackRequest to return a plain boolean and have the router
pass through its existing parsedPayload (now used for shouldIgnoreEvent
and processConnectionEventAsync). Saves ~1ms per webhook and removes
the redundant code path.
(B) Perf timing logs gated on LOG_LEVEL=debug
Adds receivedAt: number captured at the top of the webhook POST handler
in router.ts and threads it through:
processConnectionEventAsync -> SlackEventContext.{traceId,receivedAt}
-> handleSlackEvent -> per-handler HandlerMeta arg.
Each chat-style handler (handleAppMention / handleDirectMessage /
handleThreadReply, plus the triggerOnly fast path in handleSlackEvent)
emits two markers via logger.debug:
perf:thinking_sent -- ms from webhook receipt to chat.postMessage
of "Pensando..." resolved
perf:trigger_published -- ms from webhook receipt to trigger published
logger.debug is dropped below the configured min level (logger.ts:50),
so these only flow to HyperDX when LOG_LEVEL=debug is set on the pod.
Production runs (LOG_LEVEL=info) pay only the Date.now() + branch cost.
Combined with the existing "[Slack] sendMessage SUCCESS in Xms" + the
thread_messages count on the publisher's notify log, the operator can
now break down end-to-end webhook latency into pod overhead, Slack
postMessage RTT, and trigger enrichment time from logs alone.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two small perf items spun out of the latency investigation in #442:
A. Eliminate the duplicate
JSON.parseverifySlackRequestwas re-deserializingrawBodyafter the router had already parsed it. TwoJSON.parseper webhook on the same payload. The function now returns a plainbooleanand the router reuses its existingparsedPayloadforshouldIgnoreEvent+processConnectionEventAsync. Saves ~1 ms and removes a dead code branch.B. Perf-timing log gated on
LOG_LEVEL=debugreceivedAt = Date.now()is now captured at the top of the webhook POST handler inrouter.tsand threaded through:Each chat-style handler (
handleAppMention/handleDirectMessage/handleThreadReply, plus thetriggerOnlyfast path) emits two markers vialogger.debug:perf:thinking_sent— ms from webhook receipt tochat.postMessageof "Pensando..." resolving.perf:trigger_published— ms from webhook receipt to trigger published.logger.debugis dropped below the configured min level (seelogger.ts:50—if (LOG_LEVELS[level] < LOG_LEVELS[this.minLevel]) return), so these only flow to HyperDX whenLOG_LEVEL=debugis set on the pod. Production runs (LOG_LEVEL=info, the default) pay only theDate.now()+ branch cost.Combined with the existing
[Slack] sendMessage SUCCESS in Xms+ thethread_messagescount on the publisher's notify log, an operator can now decompose end-to-end webhook latency into pod overhead, SlackpostMessageRTT, and trigger-enrichment time from logs alone — without code changes.Test plan
LOG_LEVEL=info(default) → noperf:*entries in HyperDX. Bot still answers as before. Webhook latency should be marginally better (~1 ms from parse dedup).LOG_LEVEL=debug→perf:thinking_sentandperf:trigger_publishedmarkers appear in HyperDX withduration_msandtrace_id. Correlate against[Slack] sendMessage SUCCESS in Xmsfor pod-vs-Slack breakdown.triggerOnlymode emitsperf:trigger_publishedfromhandleSlackEventdirectly (no thinking_sent marker since no Pensando is sent in that mode).Summary by cubic
Removes duplicate JSON parsing in the Slack webhook path and adds debug-gated perf timing logs for chat handlers. This trims ~1 ms per webhook and lets operators break down latency from logs without code changes.
New Features
logger.debug:perf:thinking_sentandperf:trigger_publishedfor app mentions, DMs, thread replies, and thetriggerOnlypath; emitted only whenLOG_LEVEL=debug(no impact atLOG_LEVEL=info).Refactors
verifySlackRequestnow returns aboolean; the router reuses itsparsedPayloadforshouldIgnoreEventandprocessConnectionEventAsync.receivedAtin the router and threaded throughSlackEventContext(withtraceId) to support timing correlation.Written for commit 2ee57b8. Summary will update on new commits.