<?xml version='1.0' encoding='UTF-8'?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
  <channel>
    <title>LogsAPI.com — The Signal &amp; Topic Guides</title>
    <link>https://logsapi.com/</link>
    <description>Practical guides to AI logs, developer operations, workspace events, and identity evidence.</description>
    <language>en-us</language>
    <atom:link href="https://logsapi.com/rss.xml" rel="self" type="application/rss+xml"/>
    <item>
      <title>LogsAPI.com | AI Logs API | LLM, Agent &amp; Server Logging</title>
      <link>https://logsapi.com/</link>
      <guid isPermaLink="true">https://logsapi.com/</guid>
      <description>Explore AI logs APIs, LLM token usage, agent traces, server logs, workspace events, and MFA audit trails with practical guides from LogsAPI.com.</description>
    </item>
    <item>
      <title>Logs API Topic Directory | 19 Guides | LogsAPI.com</title>
      <link>https://logsapi.com/topics/</link>
      <guid isPermaLink="true">https://logsapi.com/topics/</guid>
      <description>Explore 19 LogsAPI guides for AI, LLMs, prompts, agents, server operations, mobile apps, connected work, authentication, and wallet events.</description>
    </item>
    <item>
      <title>AI Logs API Guide | Ai.LogsAPI.com</title>
      <link>https://logsapi.com/topics/ai/</link>
      <guid isPermaLink="true">https://logsapi.com/topics/ai/</guid>
      <description>Explore AI event design, request correlation, model attempts, validation outcomes, and practical controls for useful operational logs.</description>
    </item>
    <item>
      <title>LLM Logs API Guide | LLM.LogsAPI.com</title>
      <link>https://logsapi.com/topics/llm/</link>
      <guid isPermaLink="true">https://logsapi.com/topics/llm/</guid>
      <description>Learn how to observe LLM calls, model routing, response validation, interrupted streams, and the difference between requests and attempts.</description>
    </item>
    <item>
      <title>Chat Logs API Guide | Chat.LogsAPI.com</title>
      <link>https://logsapi.com/topics/chat/</link>
      <guid isPermaLink="true">https://logsapi.com/topics/chat/</guid>
      <description>Design chat logs around conversation references, turn identifiers, message state, delivery evidence, and deliberate content collection.</description>
    </item>
    <item>
      <title>Prompt Logs API Guide | Prompt.LogsAPI.com</title>
      <link>https://logsapi.com/topics/prompt/</link>
      <guid isPermaLink="true">https://logsapi.com/topics/prompt/</guid>
      <description>Explore prompt manifests, immutable template versions, retrieval references, output contracts, and tested redaction practices.</description>
    </item>
    <item>
      <title>Token Logs API Guide | Token.LogsAPI.com</title>
      <link>https://logsapi.com/topics/token/</link>
      <guid isPermaLink="true">https://logsapi.com/topics/token/</guid>
      <description>Track LLM token usage with clear provenance, accounting states, attempt identifiers, category definitions, and rate references.</description>
    </item>
    <item>
      <title>Agent Logs API Guide | Agent.LogsAPI.com</title>
      <link>https://logsapi.com/topics/agent/</link>
      <guid isPermaLink="true">https://logsapi.com/topics/agent/</guid>
      <description>Explore agent traces, tool attempts, authorization decisions, retry relationships, parallel branches, and verified execution outcomes.</description>
    </item>
    <item>
      <title>Server Logs API Guide | Server.LogsAPI.com</title>
      <link>https://logsapi.com/topics/server/</link>
      <guid isPermaLink="true">https://logsapi.com/topics/server/</guid>
      <description>Plan server logs around service identity, request outcomes, deployment context, and collection health.</description>
    </item>
    <item>
      <title>Linux Logs API Guide | Linux.LogsAPI.com</title>
      <link>https://logsapi.com/topics/linux/</link>
      <guid isPermaLink="true">https://logsapi.com/topics/linux/</guid>
      <description>Design Linux log collection with clear source boundaries, host provenance, service identity, and recovery behavior.</description>
    </item>
    <item>
      <title>Git Logs API Guide | Git.LogsAPI.com</title>
      <link>https://logsapi.com/topics/git/</link>
      <guid isPermaLink="true">https://logsapi.com/topics/git/</guid>
      <description>Connect Git revisions and repository events with actors, review decisions, and the builds that use them.</description>
    </item>
    <item>
      <title>Code Logs API Guide | Code.LogsAPI.com</title>
      <link>https://logsapi.com/topics/code/</link>
      <guid isPermaLink="true">https://logsapi.com/topics/code/</guid>
      <description>Plan code and delivery events that preserve build attempts, artifact identity, deployment outcomes, and safe diagnostic detail.</description>
    </item>
    <item>
      <title>iOS Logs API Guide | iOS.LogsAPI.com</title>
      <link>https://logsapi.com/topics/ios/</link>
      <guid isPermaLink="true">https://logsapi.com/topics/ios/</guid>
      <description>Design iOS diagnostic events around app releases, operation lifecycles, privacy decisions, and bounded collection.</description>
    </item>
    <item>
      <title>Android Logs API Guide | Android.LogsAPI.com</title>
      <link>https://logsapi.com/topics/android/</link>
      <guid isPermaLink="true">https://logsapi.com/topics/android/</guid>
      <description>Plan Android logs with useful tags, release context, operation attempts, privacy checks, and controlled diagnostic output.</description>
    </item>
    <item>
      <title>Email Logs API Guide | Email.LogsAPI.com</title>
      <link>https://logsapi.com/topics/email/</link>
      <guid isPermaLink="true">https://logsapi.com/topics/email/</guid>
      <description>Explore email event logging for message identity, delivery stages, inbound processing, retries, and privacy-aware troubleshooting.</description>
    </item>
    <item>
      <title>Phone Logs API Guide | Phone.LogsAPI.com</title>
      <link>https://logsapi.com/topics/phone/</link>
      <guid isPermaLink="true">https://logsapi.com/topics/phone/</guid>
      <description>Design phone event logs that distinguish call state, participant references, connected duration, callbacks, and workflow results.</description>
    </item>
    <item>
      <title>CRM Logs API Guide | CRM.LogsAPI.com</title>
      <link>https://logsapi.com/topics/crm/</link>
      <guid isPermaLink="true">https://logsapi.com/topics/crm/</guid>
      <description>Plan CRM audit and synchronization logs around object changes, actor identity, revisions, integration attempts, and conflict decisions.</description>
    </item>
    <item>
      <title>Calendar Logs API Guide | Calendar.LogsAPI.com</title>
      <link>https://logsapi.com/topics/calendar/</link>
      <guid isPermaLink="true">https://logsapi.com/topics/calendar/</guid>
      <description>Explore calendar event logging for recurrence, time zones, attendee responses, cancellations, and cross-application scheduling workflows.</description>
    </item>
    <item>
      <title>MFA Logs API Guide | MFA.LogsAPI.com</title>
      <link>https://logsapi.com/topics/mfa/</link>
      <guid isPermaLink="true">https://logsapi.com/topics/mfa/</guid>
      <description>Design MFA audit events for challenge verification, enrollment, recovery, policy decisions, session outcomes, and secret-safe diagnostics.</description>
    </item>
    <item>
      <title>Wallet Logs API Guide | Wallet.LogsAPI.com</title>
      <link>https://logsapi.com/topics/wallet/</link>
      <guid isPermaLink="true">https://logsapi.com/topics/wallet/</guid>
      <description>Understand wallet event logging for request handling, transaction identity, chain observations, network scope, and safe reconciliation.</description>
    </item>
    <item>
      <title>Tokenized Logs API Guide | Tokenized.LogsAPI.com</title>
      <link>https://logsapi.com/topics/tokenized/</link>
      <guid isPermaLink="true">https://logsapi.com/topics/tokenized/</guid>
      <description>Plan tokenized asset logs around contract identities, exact quantities, decoding versions, block context, and off-chain workflow evidence.</description>
    </item>
    <item>
      <title>The Signal | Logging, AI &amp; Observability Guides | LogsAPI.com</title>
      <link>https://logsapi.com/blog/</link>
      <guid isPermaLink="true">https://logsapi.com/blog/</guid>
      <description>Read The Signal: 10 practical guides to AI event design, token logging, agent tracing, server pipelines, mobile diagnostics, MFA, and workspace events.</description>
    </item>
    <item>
      <title>AI Logs API: A Practical Guide to Useful Events</title>
      <link>https://logsapi.com/blog/ai-logs-api-guide/</link>
      <guid isPermaLink="true">https://logsapi.com/blog/ai-logs-api-guide/</guid>
      <description>Design AI events that connect requests, model attempts, validation, and outcomes without filling logs with sensitive content.</description>
      <pubDate>Sat, 08 Feb 2025 00:00:00 GMT</pubDate>
      <category>AI &amp; LLM</category>
      <content:encoded><![CDATA[<p>A useful AI log explains what happened around a model interaction well enough to investigate it later. It connects the application request, the selected workflow, the model attempt, and the result the application accepted. It does not need to preserve every message or turn a troubleshooting system into a second copy of customer data. The design starts with decisions: what would an engineer need to know when a response is slow, incomplete, rejected, or unexpectedly expensive?</p>
<p>This guide develops a practical event contract for those questions. The field names and examples are illustrative application conventions to adapt to an actual implementation. The <a href="https://logsapi.com/topics/ai/">AI logging topic hub</a> provides a starting point for related terminology and recommended fields.</p>
<h2>Start with the questions your events must answer</h2>
<p>Write down three investigations before writing instrumentation. For a slow response, you may need to separate queue time, retrieval time, model time, and application processing. For an invalid response, you need the prompt version, output contract, validation result, and fallback decision. For a sudden usage increase, you need the workflow, number of attempts, and usage reported for each attempt.</p>
<p>Turn those questions into an event inventory. An event should represent an observable change or completed operation: a request was accepted, retrieval finished, a model attempt ended, or an output failed validation. Avoid messages such as “AI working” that lack a stable meaning. Give each event an owner who can explain when it fires and what its fields mean.</p>
<h3>Separate transport success from application success</h3>
<p>A successful network response can still contain output your application cannot use. Record the transport result and application validation result separately. If an answer passes a JSON parser but omits a required business field, the event should preserve that distinction. Otherwise, dashboards can report success while users repeatedly encounter failures.</p>
<h2>Build a small, consistent event envelope</h2>
<p>Use a common envelope across workflows before adding model-specific attributes. The <a href="https://opentelemetry.io/docs/specs/otel/logs/data-model/" target="_blank" rel="noopener noreferrer">OpenTelemetry Logs Data Model</a> distinguishes event time from observation time and provides places for severity, trace context, resource information, and attributes. That distinction is useful when records arrive late or move through several collection stages. Align an implementation with the relevant specification instead of assuming a handwritten JSON object is already compliant.</p>
<p>For an application-level design, begin with an event name, schema version, event identifier, timestamp, service, environment, and request identifier. Add an outcome with a documented vocabulary. Keep values typed consistently: durations as numbers in a named unit, counts as integers, and missing values as explicitly unknown rather than arbitrary text.</p>
<pre><code>{
  "event_name": "model.attempt.completed",
  "schema_version": 1,
  "event_id": "evt_example_01",
  "request_id": "req_example_01",
  "attempt_number": 1,
  "workflow": "document_summary",
  "outcome": "validated",
  "prompt_version": "summary-v3"
}</code></pre>
<p>This simplified example describes a completed attempt without including a document, prompt, response, or secret. A real contract also needs time, source, and collection fields appropriate to the chosen telemetry system.</p>
<h2>Describe the full request lifecycle</h2>
<p>A practical lifecycle includes acceptance, preparation, execution, validation, and completion. Record each boundary only when it helps reconstruct behavior. Preparation might involve selecting a prompt template and retrieving documents. Execution might involve one model call or several. Validation decides whether the returned material satisfies the application’s rules. Completion describes what the application ultimately delivered.</p>
<p>Give the overall request its own outcome. A first attempt may fail and a fallback may succeed; both facts matter. If the only record says “success,” engineers lose the retry history. If the only record says “error,” they may mistake a recovered attempt for a failed user task. Use an overall request identifier to join the lifecycle and distinct attempt identifiers for individual executions.</p>
<p>Include cancellation and timeout paths in the design. A client disconnect does not necessarily prove that remote processing stopped. Where the remote outcome cannot be established, preserve an unknown state and allow a later reconciliation event to clarify it.</p>
<h2>Normalize carefully across providers and workflows</h2>
<p>A shared schema makes comparison easier only when shared fields retain the same meaning. Define what “duration” measures, when an attempt begins, and whether usage values are estimates or observed totals. Keep original provider field names in a documented mapping outside ordinary event bodies, and retain only the bounded metadata needed to investigate mapping errors.</p>
<p>Do not force every provider-specific field into a generic total. Unsupported values should remain unavailable. Different request types may report different usage categories, and a field called “tokens” can hide several accounting choices. The <a href="https://logsapi.com/blog/llm-token-usage-logging/">guide to LLM token logging</a> explains how to preserve those distinctions without confusing estimates, usage, and cost.</p>
<h2>Choose identifiers for correlation, not exposure</h2>
<p>Use opaque identifiers to connect related events. A request identifier should not contain an email address, document title, phone number, or prompt fragment. Keep the identifier’s scope clear: one user interaction, one background job, or one model attempt. Reusing a single session identifier for every operation makes individual investigations harder and can expose an unnecessarily broad history.</p>
<p>Separate high-cardinality identifiers from labels used for aggregate metrics. A request ID is valuable for finding one event sequence, but grouping every measurement by request ID creates a different series for each request. Use bounded dimensions such as workflow and outcome for summaries, then follow identifiers into detailed records when an investigation requires it.</p>
<h2>Make content capture a deliberate exception</h2>
<p>Start by recording metadata that answers the intended questions. Prompt template versions, input size, output format, validation codes, and redaction outcomes can often explain a failure without storing customer text. If a particular investigation requires content, define its purpose, collection scope, access rules, and deletion plan before enabling capture.</p>
<p>Review hidden copies as carefully as the main event body. Exceptions, debug middleware, request headers, retriever results, and serialized tool arguments can introduce data that an application developer never intentionally logged. The <a href="https://logsapi.com/blog/prompt-versioning-and-redaction/">prompt logging and redaction guide</a> describes a version-based approach that keeps ordinary operational records useful while reducing unnecessary content exposure.</p>
<h2>Design for delayed, duplicated, and missing events</h2>
<p>Treat collection as its own system with observable failure modes. A process can stop before a buffer flushes. A collector can reject an oversized record. A retry can deliver the same event twice. Decide which events may be dropped under pressure, which need durable buffering, and how the application should behave when logging cannot proceed.</p>
<p>Use an event identifier to recognize retransmission of the same record. A retried model operation is a new attempt, while a retried export of an existing event is a delivery duplicate. Preserve that difference. Reconstruct sequences with explicit relationships and timestamps rather than assuming records arrive in execution order.</p>
<p>Monitor the collection path with bounded counters for rejected records, export failures, queue age, and dropped batches. Keep those signals independent enough to reveal a broken log pipeline. A silent collector can otherwise make a service look healthy simply because its error records stopped arriving.</p>
<h2>Review events with an investigation exercise</h2>
<p>Before expanding instrumentation, walk through a small set of synthetic cases: ordinary success, invalid output, a recovered retry, cancellation, and collection failure. Ask someone unfamiliar with the implementation to reconstruct each outcome using only the emitted metadata. Any answer that requires undocumented assumptions identifies a gap in the event contract.</p>
<p>Then inspect the data itself. Check that field types match the contract, identifiers connect the intended operations, sensitive values are absent, and timestamps use the declared format. Review a proposed schema change against existing readers. Adding a field is usually easier to absorb than silently changing the unit or meaning of a field already used in alerts.</p>
<h2>Follow one concrete failure through the record</h2>
<p>Imagine a summary request that reaches the model successfully but fails the application’s required-field check. Start with the request outcome, follow its attempt identifier, and inspect the validation code and prompt version. Compare the same workflow before and after that version changed. If transport results remain stable while one validation code rises, investigate the prompt and output contract before changing the collection infrastructure. This sequence is an illustrative investigation, not proof of a particular cause. The record should help narrow the next question and preserve enough context to test it.</p>
<h2>Conclusion: collect evidence that supports a decision</h2>
<p>Strong AI logs connect a request to its attempts, decisions, and final outcome through a small, documented event contract. Begin with the investigations that matter, preserve uncertainty, and make collection failures visible. Expand only when a new field answers a real question. This produces an operational record that engineers can interpret consistently as workflows, providers, and application requirements evolve.</p>]]></content:encoded>
    </item>
    <item>
      <title>LLM Token Logging: Measure Usage, Latency, and Cost</title>
      <link>https://logsapi.com/blog/llm-token-usage-logging/</link>
      <guid isPermaLink="true">https://logsapi.com/blog/llm-token-usage-logging/</guid>
      <description>Build an interpretable record of LLM usage, timing, retries, and cost estimates while preserving incomplete accounting states.</description>
      <pubDate>Fri, 06 Jun 2025 00:00:00 GMT</pubDate>
      <category>AI &amp; LLM</category>
      <content:encoded><![CDATA[<p>LLM usage becomes difficult to explain when one “request” can include a long conversation, retrieved documents, several model attempts, and multiple tool calls. A single token total does not tell you which work produced it. A single duration does not explain where a user waited. Useful token logging connects usage and timing to the operation that consumed the resources, then preserves enough context to compare like with like.</p>
<p>The goal is an accounting record that supports engineering decisions. You should be able to investigate growing prompts, repeated retries, incomplete streams, and unexpected allocation changes without retaining the actual conversation. Begin with the terminology in the <a href="https://logsapi.com/topics/llm/">LLM logging hub</a>, then define the measurements your application can obtain reliably.</p>
<h2>Keep estimates, observed usage, and charges separate</h2>
<p>A preflight token estimate answers whether a proposed input appears to fit a chosen budget. Observed usage describes what a provider reports for a completed or partially completed operation. An invoiced charge describes the commercial accounting of that work. These are related measurements with different purposes and different uncertainty.</p>
<p>For example, <a href="https://platform.claude.com/docs/en/build-with-claude/token-counting" target="_blank" rel="noopener noreferrer">Anthropic’s token-counting documentation</a> describes token counting before message creation and explicitly characterizes its result as an estimate that can differ from actual input usage. This supports a practical rule: label estimates as estimates, and preserve observed values separately when they become available. Do not silently overwrite one with the other.</p>
<p>Use a provenance field such as <code>usage_source</code> and an availability field such as <code>usage_state</code>. Their allowed values should come from your documented contract. Missing usage is not zero usage. A timeout can leave accounting unresolved even when the application has already reported a failure.</p>
<h2>Choose the right accounting unit</h2>
<p>Record usage against an individual model attempt, and connect attempts to an overall request or run. If a summarization job retries once, retain both attempts. The final answer may come from the second attempt, while both attempts may matter when reconciling usage. A fallback to a different model also needs a distinct record and the identity of the model actually used.</p>
<p>Decide whether a usage record is an immutable final observation or an update that replaces an earlier observation. Both designs can work. Mixing them produces double counting. If updates replace earlier values, include an observation version and a stable accounting key. If records are immutable, represent corrections explicitly and define how aggregation applies them.</p>
<p>The <a href="https://logsapi.com/topics/token/">token accounting topic hub</a> collects the recommended fields and boundary questions that help keep this contract understandable.</p>
<h2>Use a narrow, typed usage event</h2>
<p>The following record illustrates a possible application-level shape. Its identifiers and values are fictional, and its names are not a universal provider schema.</p>
<pre><code>{
  "event_name": "model.usage.observed",
  "request_id": "req_example_04",
  "attempt_id": "attempt_example_02",
  "usage_source": "provider_response",
  "usage_state": "complete",
  "input_tokens": 1200,
  "output_tokens": 180,
  "duration_ms": 2400,
  "accounting_version": 1
}</code></pre>
<p>Store counts as integers and timing in a declared unit. Preserve provider-specific categories when they affect interpretation, but document whether each category is included in another total. A cached-input field, for example, must not be added to a total that already contains it. Only calculate a normalized total after validating the selected provider’s definitions.</p>
<h3>Make the model identity precise enough to compare</h3>
<p>Keep a safe model identifier, provider identifier, and application configuration version. If a routing alias can resolve to different models, record the requested alias and observed model separately when available. An aggregate labeled only “default” becomes hard to interpret after its routing configuration changes.</p>
<h2>Handle streams and interruptions explicitly</h2>
<p>For a streaming response, establish when usage becomes authoritative for your integration. Some information may arrive only near completion. Buffer the accounting state until the integration knows which observation is final. Do not assume every chunk carries an independent count, and do not sum cumulative counters as though they were deltas.</p>
<p>Track the stream outcome independently: completed, interrupted, cancelled, or unknown are useful starting concepts. If a stream ends before the application receives final accounting, preserve the partial evidence and mark its coverage. A downstream connection failure should not turn an unavailable usage field into zero merely to keep a dashboard calculation simple.</p>
<p>Test this behavior with synthetic interrupted streams. The useful question is whether a reader can tell what is known, what is incomplete, and whether a later observation should replace or supplement the record.</p>
<h2>Measure latency where users experience it</h2>
<p>Define the boundaries of each duration. Application latency might begin when a task is accepted and end when its result is usable. Model-call latency might begin immediately before an invocation and end after the response is processed. Queue time, retrieval, retries, and output validation can explain the difference between those measurements.</p>
<p>For a streaming experience, record the time to the first meaningful output separately from total completion time, if your integration exposes those moments. State precisely whether that first output means any received event, the first text fragment, or the first material displayed to a user. Otherwise, implementations can use the same metric name for different experiences.</p>
<p>Use a monotonic clock for elapsed duration inside one process when available. Wall-clock timestamps help correlate records, but clock adjustments can distort a duration calculated by subtracting them. For work crossing process boundaries, preserve the measurement location and avoid pretending that independently measured clocks form a perfectly synchronized stopwatch.</p>
<h2>Calculate cost from a versioned rate reference</h2>
<p>Keep the usage event independent of a current rate table. A cost estimate can reference a separate, dated rate definition with an explicit currency, unit, model, and relevant usage category. This allows an investigator to explain how an estimate was calculated without placing commercial terms or mutable configuration into every event.</p>
<p>For each non-overlapping category, divide the token count by the rate’s token unit, multiply by the applicable rate, and then sum the results. Account separately for any relevant charge that is not token-based. Preserve the assumptions and rate-reference version. Label the result as an estimate until it has been reconciled with the authoritative billing record.</p>
<p>Do not revise historical estimates merely because today’s rate reference changes. If a correction is necessary, keep its reason and effective period. This makes comparisons reproducible and prevents an unexplained shift in a historical dashboard.</p>
<h2>Compare workloads before comparing totals</h2>
<p>Group analysis by a small set of meaningful dimensions: workflow, model, prompt version, outcome, and deployment environment. Separate experimental runs from production traffic. A batch of long-document summaries should not be evaluated against short chat replies without accounting for the different work each performs.</p>
<p>Inspect distributions as well as totals. A rising average may reflect a few unusually long inputs or a broad increase across all requests. Examine request counts, typical input sizes, upper-range durations, and retry frequency together. Token totals alone cannot tell whether the application grew, its workload changed, or a defect caused repeated work.</p>
<p>When prompt changes are involved, connect the measurement to a version rather than the prompt text. The <a href="https://logsapi.com/blog/prompt-versioning-and-redaction/">prompt versioning guide</a> explains how to preserve that reference while keeping user content out of routine logs.</p>
<h2>Make accounting completeness visible</h2>
<p>A usage dashboard should state what fraction of operations has complete accounting. Count missing observations, unresolved attempts, and rejected usage records alongside recorded totals. If a deployment changes the usage parser, compare coverage before interpreting a sudden reduction as an efficiency improvement.</p>
<p>Test one clean success, one retry, one stream interruption, and one duplicated export. Verify that a request-level total includes the intended attempts exactly once. For multi-step workflows, follow the <a href="https://logsapi.com/blog/agent-tool-call-tracing/">agent tracing guide</a> to connect model usage to the tool sequence that caused it.</p>
<h2>Audit a small ledger before trusting a large total</h2>
<p>Consider a fictional request with two model attempts and three exported usage records because the second record was delivered twice. A correct aggregation should recognize two attempts and one delivery duplicate. If the first attempt has incomplete accounting, the request total should also expose that gap. Write the expected result down before inspecting the dashboard. Then introduce a corrected observation and confirm that it follows the contract’s replacement or adjustment rule. This small exercise can reveal double counting and silent missing values more clearly than a large aggregate.</p>
<h2>Conclusion: preserve meaning alongside the numbers</h2>
<p>Reliable LLM token logging gives every count a source, every duration a boundary, and every cost estimate a reproducible set of assumptions. Keep attempt-level records, preserve incomplete states, and validate aggregation with realistic failure paths. Those choices make usage trends explainable without collecting the sensitive conversations behind them.</p>]]></content:encoded>
    </item>
    <item>
      <title>Prompt Logging Without Leaking Sensitive Data</title>
      <link>https://logsapi.com/blog/prompt-versioning-and-redaction/</link>
      <guid isPermaLink="true">https://logsapi.com/blog/prompt-versioning-and-redaction/</guid>
      <description>Use immutable prompt versions, safe metadata, and tested redaction boundaries to investigate AI behavior without routine transcript capture.</description>
      <pubDate>Fri, 04 Apr 2025 00:00:00 GMT</pubDate>
      <category>AI &amp; LLM</category>
      <content:encoded><![CDATA[<p>Prompt logs can be useful long before they contain prompt text. A template identifier, its immutable version, the application release, and the validation outcome often explain why an AI feature behaved differently after a change. Capturing the full assembled prompt creates a much broader record: it may include user messages, retrieved documents, account details, hidden configuration, and tool output that originated in several systems.</p>
<p>A sound design separates the information needed to understand a prompt from the content supplied to it. This guide describes that separation, how to version prompt changes, and how to evaluate redaction when content capture has a defined purpose. The <a href="https://logsapi.com/topics/prompt/">prompt logging hub</a> provides a compact checklist of useful metadata.</p>
<h2>Build a prompt manifest before capturing content</h2>
<p>A prompt manifest is a proposed application record describing how an input was assembled. It can reference a template, a version, a retrieval configuration, an output contract, and the classes of variables inserted into the template. It should avoid copying the variables themselves. This gives an investigator a map of the input’s structure without turning every event into a content archive.</p>
<p>For a document-summary workflow, the manifest might state that template “summary” version three was used with two retrieved documents, a particular output schema, and a bounded input-size measurement. When validation failures rise, an engineer can compare versions and input sizes before requesting access to any underlying document.</p>
<p>Keep the manifest concise. Record a field only if a specific investigation or control needs it. A complete inventory of every configuration value can reveal internal information while making the relevant change harder to find.</p>
<h2>Give each prompt change an immutable identity</h2>
<p>Assign a new version when a template or its behaviorally relevant configuration changes. An alias such as “current” is useful for selecting a configuration but insufficient for historical investigation. Log both the selected alias and the resolved version if the distinction matters. Preserve the resolved template in the controlled configuration system responsible for it.</p>
<p>Document what belongs to a version. Examples include instruction text, variable definitions, output requirements, and the order in which input sections are assembled. If retrieval settings change independently, give them a separate version rather than hiding the change behind the prompt name.</p>
<h3>Use references without promising exact replay</h3>
<p>A version identifies configuration; it does not guarantee that a future run will reproduce an earlier answer. The source documents, application state, and model behavior may differ. Describe a replay as a new execution under recorded conditions, and record any unavailable inputs. For routine diagnostics, a reproducible configuration reference is still substantially more useful than a mutable label.</p>
<h2>Define the safe event before the sensitive event</h2>
<p>Decide what ordinary operations should emit when no content capture is enabled. The following fictional record is a suggested application shape, not a universal schema or a live API contract.</p>
<pre><code>{
  "event_name": "prompt.assembled",
  "request_id": "req_example_07",
  "template_id": "document_summary",
  "template_version": "v3",
  "input_classes": ["user_text", "retrieved_document"],
  "content_capture": "disabled",
  "output_contract": "summary_fields_v2"
}</code></pre>
<p>This event supports version comparisons without exposing the user’s words. Add safe error codes when assembly fails, such as a missing required variable or an unsupported input type. Avoid logging a rejected variable value simply because it appears inside an exception message.</p>
<p>The <a href="https://cheatsheetseries.owasp.org/cheatsheets/Logging_Cheat_Sheet.html" target="_blank" rel="noopener noreferrer">OWASP Logging Cheat Sheet</a> advises against directly recording passwords, access tokens, encryption keys, and other sensitive information. Apply that principle to prompt inputs and the surrounding instrumentation, including headers and diagnostic output. Masking only the main prompt field leaves other copies unaddressed.</p>
<h2>Redact before the first durable copy</h2>
<p>Map the path from prompt assembly to every destination that can retain it. That path may include an application logger, local file, queue, collector, error tracker, or developer console. Place the primary content-selection and redaction boundary before the earliest persistent copy under your control. A filter at the final storage destination cannot remove copies already written elsewhere.</p>
<p>Prefer an allowlist of fields whose purpose and sensitivity have been reviewed. Use redaction rules as an additional layer for content that still must pass through. Structured input fields are easier to classify deliberately than a single large string assembled from several sources. Keep the classification associated with each source until the logging decision has been made.</p>
<p>When a redactor fails, use a bounded failure event that contains the rule-set version and a safe error code. Do not fall back to logging the original payload for debugging. Decide separately whether the application operation can continue under its normal business requirements.</p>
<h2>Understand the limits of masking and hashing</h2>
<p>A marker such as <code>[REDACTED_EMAIL]</code> can preserve a field’s role without preserving its value. Make markers distinguishable from text a user could naturally enter, or keep the redaction metadata separately. An investigator should be able to tell that the logger removed a value rather than assume the original prompt contained the marker.</p>
<p>Hashing is not an automatic anonymity guarantee. A predictable input can be tested against its hash, and a stable identifier can still link a person’s activities across records. Use opaque identifiers when ordinary correlation is sufficient. If a keyed transformation is necessary, restrict its scope, manage the key separately, and treat the resulting identifiers as sensitive operational data.</p>
<p>Text detectors also have limits. Sensitive material can be embedded in an attachment, split across fields, or described indirectly. Review what information a field reveals in combination with other fields, and do not treat a successful detector pass as proof that unrestricted collection is safe.</p>
<h2>Test redaction with synthetic examples</h2>
<p>Create a small fixture set containing fictional emails, obvious test credentials, multiline input, Unicode text, nested objects, and intentionally malformed data. Define the expected safe output for each case. Include exception paths and logging-library failures, since those paths can bypass the formatting used for successful requests.</p>
<p>Test two outcomes: unwanted content is absent, and the remaining event still answers its diagnostic question. Removing the entire record can conceal an important failure. Keeping a safe reason code, request identifier, and affected stage can preserve the event’s meaning without retaining the rejected content.</p>
<p>Review the exported result, not just the redactor’s return value. A framework may separately capture request bodies or exception context. Run the fixtures through the whole collection path and inspect every destination included in the logging design.</p>
<h2>Control access and expiration by purpose</h2>
<p>If a documented investigation needs a content sample, define who can enable that capture, which traffic it covers, who can read it, and when it expires. Keep its access narrower than the ordinary metadata view. Record configuration changes and access events so the exception can be reviewed later.</p>
<p>Set retention according to the purpose of each record class. A template reference and a sampled conversation need not have the same lifetime. Include exports, support attachments, and backups in the deletion design, and make practical deletion limits visible to the people responsible for the data.</p>
<p>For conversational systems, the <a href="https://logsapi.com/topics/chat/">chat logging hub</a> explains how turn identifiers and message-state metadata can support investigation without retaining whole transcripts.</p>
<h2>Review outputs and connected tools as well</h2>
<p>Prompt privacy work should include model responses and tool results. A response may repeat material from its input, while a retrieval result may carry information that was never visible in the original user message. Apply the same collection purpose and access boundaries to those records.</p>
<p>Coordinate the prompt manifest with the <a href="https://logsapi.com/blog/agent-tool-call-tracing/">agent execution trace</a> when tools are involved. Record which tool contributed a result and which prompt version consumed it, while keeping the tool’s arguments and returned content subject to their own field review.</p>
<h2>Connect evaluation results to the same version</h2>
<p>Use the prompt version in evaluation records as well as operational events. Record an evaluation-set identifier, its version, the relevant output contract, and the result of each defined check. Keep private examples in their controlled source rather than copying them into evaluation logs. When a prompt change improves one check and weakens another, these references let reviewers inspect the intended comparison. Record reviewer decisions separately from automatic scores, and avoid treating either as proof that all future inputs will behave the same way.</p>
<h2>Conclusion: preserve context with less content</h2>
<p>Useful prompt logging begins with immutable configuration references and deliberate metadata. Redaction then protects narrowly defined content capture, with failure behavior and access boundaries that can be inspected. Review the complete collection path, test with synthetic material, and retain only what serves a clear purpose. That approach supports investigations while keeping sensitive prompt content out of routine operational records.</p>]]></content:encoded>
    </item>
    <item>
      <title>Agent Logs: Trace Tool Calls, Retries, and Outcomes</title>
      <link>https://logsapi.com/blog/agent-tool-call-tracing/</link>
      <guid isPermaLink="true">https://logsapi.com/blog/agent-tool-call-tracing/</guid>
      <description>Connect agent runs to their tool calls, permissions, retries, parallel work, and final outcomes through a clear execution record.</description>
      <pubDate>Sun, 28 Dec 2025 00:00:00 GMT</pubDate>
      <category>AI &amp; LLM</category>
      <content:encoded><![CDATA[<p>An agent run can contain several model calls, branching tool requests, retries, and work that continues after the original interaction ends. A transcript alone cannot reliably explain that execution. To investigate it, you need a record of what the system attempted, which checks allowed the action, what the tool reported, and how the application established its final outcome.</p>
<p>Agent logging works best when it follows the structure of the work. Give the whole run an identity, give each logical step an identity, and distinguish individual attempts. This guide develops that structure with practical examples. The <a href="https://logsapi.com/topics/agent/">agent logging hub</a> summarizes the main event boundaries and recommended fields.</p>
<h2>Use a trace to represent related operations</h2>
<p>The <a href="https://opentelemetry.io/docs/concepts/signals/traces/" target="_blank" rel="noopener noreferrer">OpenTelemetry explanation of traces</a> describes spans as units of work with timing, context, and attributes. Related spans can share a trace identifier and use parent relationships to describe sub-operations. Apply that idea to an agent run: the run contains steps, while a step may contain model invocations, validation, and tool execution.</p>
<p>Trace structure supplies execution relationships; application events supply their meaning. A tool span lasting two seconds does not by itself explain whether the tool returned valid data, performed a requested change, or produced a result the agent ignored. Add bounded outcome fields and events for the decisions that matter.</p>
<p>Choose stable operation names such as “document.lookup” or “record.update.” Keep a customer’s name, document content, or full command out of the span name. Stable names also make aggregate analysis easier.</p>
<h2>Separate runs, steps, calls, and attempts</h2>
<p>A run is the overall application task. A step is a logical unit inside that task. A tool call is the system’s request to perform a particular operation. An attempt is one execution of that request. Document these definitions because frameworks may use the same words differently.</p>
<p>When a call is retried, preserve the logical call identifier and create a new attempt identifier. When the agent revises its plan and makes a materially different request, create a new call identifier. That distinction helps an investigator tell recovery from new work. It also makes repeated actions visible without relying on timestamps or similar-looking argument text.</p>
<p>Keep an event identifier separate from all of these. Re-exporting the same event should retain its event identity, while performing the operation again should create a new attempt. Otherwise, a delivery duplicate can look like an extra tool execution.</p>
<h2>Log the boundary around every consequential tool</h2>
<p>A useful tool sequence records request creation, argument validation, authorization, execution, result validation, and the final application decision. Not every stage needs a separate record; combine stages when their relationship remains clear. The requirement is that an investigator can establish what happened at each meaningful boundary.</p>
<p>This fictional event illustrates a completed read operation. Its fields are suggested application conventions, not an operational endpoint or a framework standard.</p>
<pre><code>{
  "event_name": "agent.tool_attempt.completed",
  "run_id": "run_example_12",
  "step_id": "step_example_03",
  "tool_call_id": "call_example_08",
  "attempt_number": 1,
  "tool_name": "document.lookup",
  "authorization_outcome": "allowed",
  "execution_outcome": "completed",
  "result_validation": "accepted"
}</code></pre>
<p>Log a tool’s stable name and version when the version affects behavior. Prefer a classified input description and an opaque resource reference over raw arguments. A lookup term can itself contain customer information, and an output object can contain more information than the agent needs to preserve.</p>
<h2>Keep authorization evidence connected to execution</h2>
<p>For an action with access or change implications, record which policy decision applied and which permission scope was evaluated. Use a safe policy identifier and decision reason. The fact that a model requested a tool does not establish that the application authorized its execution.</p>
<p>If a human review is part of the workflow, distinguish approval requested, approval received, approval declined, and approval expired. Bind a decision to the specific action and the version of its arguments that was reviewed. If the action changes afterward, the earlier review should remain associated with its original request.</p>
<p>Keep identity records appropriately protected. An opaque actor reference and actor type can be enough for routine operational analysis. The <a href="https://logsapi.com/blog/mfa-authentication-audit-logs/">authentication and MFA audit-log guide</a> explains related distinctions between an identity event, an access decision, and an application outcome.</p>
<h2>Represent retries and uncertain outcomes honestly</h2>
<p>A timeout tells you that one observer stopped waiting. It does not necessarily tell you whether a remote change occurred. Record the timeout and the last confirmed execution stage. For a consequential action, use an explicit unresolved outcome until the application can reconcile the remote state.</p>
<p>Where the destination supports an idempotency mechanism, use its documented behavior to reduce the risk of repeating a change. Record a safe reference to that mechanism and the retry relationship. Do not assume that repeating the same arguments is automatically safe, or that a logging identifier itself enforces idempotency.</p>
<h3>Separate recovery from reconciliation</h3>
<p>A recovery attempt tries to complete the task. Reconciliation determines what a previous uncertain attempt actually did. Record them as distinct operations. An illustrative update might time out, then a read operation checks whether the requested version exists. That check provides new evidence; it should not erase the fact that the original observer saw a timeout.</p>
<p>Bound retries with an application policy, and record the reason when the policy stops further attempts. A run ending because its attempt budget was exhausted needs a different outcome from a run stopped by an access decision.</p>
<h2>Preserve context across queues and parallel work</h2>
<p>When a step moves to a queue, carry the correlation context in the approved message metadata and record the queue boundary. The worker should retain enough context to connect its result to the originating run. Keep message identifiers and delivery attempts distinct from tool-call identifiers and execution attempts.</p>
<p>For parallel branches, preserve the parent relationship and a branch identifier. Record when a branch finishes and how the joining step uses its result. If the run ends while a branch remains active, indicate whether that branch was cancelled, detached deliberately, or left unresolved.</p>
<p>Span links can express relationships that do not fit a simple parent-child tree, including work resumed in a separate trace. Use the tracing system’s actual context APIs and verify the emitted relationships. Copying a trace identifier into an arbitrary field does not by itself create a valid distributed trace.</p>
<h2>Measure time and usage at the right scope</h2>
<p>Measure total run duration separately from individual step durations. Parallel steps overlap, so their durations cannot simply be added to reconstruct elapsed wall time. Queue waiting, approval waiting, model execution, and tool execution also describe different causes of delay and should remain distinguishable when they matter to the user experience.</p>
<p>Attach model usage to the attempt that consumed it, then define how run-level totals include those attempts. The <a href="https://logsapi.com/blog/llm-token-usage-logging/">LLM usage logging guide</a> explains how to avoid duplicated counts and preserve accounting gaps. A run can have a known application outcome while some usage remains incomplete.</p>
<h2>Record observable decisions without unnecessary content</h2>
<p>Capture the selected tool, the validated action, the policy result, and a bounded reason code for application decisions. Preserve relevant configuration versions and safe evidence references. These records describe behavior that the application can verify without requiring unrestricted collection of model text.</p>
<p>Apply the same content controls to tool arguments, tool responses, exception details, and intermediate model outputs. The <a href="https://logsapi.com/blog/prompt-versioning-and-redaction/">prompt privacy guide</a> describes a metadata-first approach. Treat logging controls as part of the tool boundary so that one verbose integration does not silently bypass the rest of the system’s collection policy.</p>
<h2>Define the final run record</h2>
<p>End a run with an application outcome that explains whether the requested task was completed, partially completed, declined, cancelled, or left unresolved. Record the last confirmed step and any outstanding operation references. A tool’s successful response should influence this result only after the application has validated what that response means. If the user-facing answer reports completion while a consequential operation remains uncertain, the inconsistency should be visible in the record. Keep subsequent reconciliation attached to the run so reviewers can distinguish the original report from later evidence.</p>
<h2>Conclusion: make a run reconstructable</h2>
<p>A useful agent trace connects each run to its steps, attempts, permissions, and verified outcomes. Before relying on it, inspect synthetic cases covering retries, declined actions, parallel branches, and uncertain remote results. A reader should be able to identify the last confirmed state and the evidence behind the final decision. That is the practical standard for agent logs that support debugging and operational review.</p>]]></content:encoded>
    </item>
    <item>
      <title>Server and Linux Logs: Build a Reliable Collection Pipeline</title>
      <link>https://logsapi.com/blog/server-linux-log-pipelines/</link>
      <guid isPermaLink="true">https://logsapi.com/blog/server-linux-log-pipelines/</guid>
      <description>A practical approach to collecting server and Linux events, preserving useful context, and handling gaps, retries, and sensitive data.</description>
      <pubDate>Fri, 08 Mar 2024 00:00:00 GMT</pubDate>
      <category>Developer Operations</category>
      <content:encoded><![CDATA[<p>A server log pipeline should help an engineer explain what happened when a service became slow, restarted, or stopped accepting work. Collecting every available message does not automatically produce that explanation. A useful pipeline preserves the relationship between a request, the process that handled it, the machine that hosted it, and the delivery path that carried its events. It also makes missing information visible. Start with those questions before selecting collectors or increasing retention.</p>
<p>This guide describes a practical design for Linux services and their surrounding infrastructure. The field names and examples are recommendations for an application event contract, not a universal logging specification. Adapt them to your runtime, operating system, and existing tools. The <a href="https://logsapi.com/topics/server/">server logging guide</a> provides a starting point for choosing operational events.</p>
<h2>Inventory the events you actually need</h2>
<p>List the systems involved in one important user journey. For an API request, that might include a reverse proxy, an application process, a job queue, and a worker. Give every source an owner and describe the question its logs answer. Proxy events may explain connection outcomes, while application events explain validation failures or completed operations. Machine events can provide context about restarts and resource pressure.</p>
<p>Keep these purposes distinct. An application timeout does not prove that the host ran out of memory. A service restart does not explain whether a customer request completed first. Plan the joins between sources instead of translating every event into one vague message field. For each source, record its format, collection location, expected event rate, sensitivity, and behavior when its output destination becomes unavailable.</p>
<h2>Define a small, consistent event contract</h2>
<p>Begin with an event name, event identifier, source timestamp, service name, environment, outcome, and schema version. Include a request identifier when the event belongs to a request. Add a deployment identifier so an investigation can separate releases that ran during the same incident. Use a stable logical service name; a temporary process identifier can be a useful additional attribute, but it is a poor replacement for service identity.</p>
<p>Choose types deliberately. A duration should be numeric with an explicit unit, such as <code>duration_ms</code>. An outcome should come from a documented set, such as <code>success</code>, <code>failure</code>, or <code>canceled</code>. Distinguish an absent field from an empty string and an actual zero. These decisions make later queries easier to interpret and prevent each team from creating a subtly different definition of the same event.</p>
<h2>Respect the boundary between collection formats</h2>
<p>A file containing one JSON object per line, a system journal, and a container output stream are different inputs. Give each input an appropriate reader and parser. When services use the systemd journal, its <a href="https://systemd.io/JOURNAL_EXPORT_FORMATS/">official journal export documentation</a> describes both an export format and a JSON representation. Journal JSON fields are not always simple strings. Binary values become byte arrays, repeated fields become arrays of values, and an oversized field becomes null when the serializer is configured to omit its value.</p>
<p>Consequently, validate field types before mapping journal records into your application contract. Preserve the original source identity alongside normalized names, and put unsupported values through an explicit handling path. Decide how to represent a multiline exception as one event. Do not assume that splitting every input on newline boundaries is safe for every format. The <a href="https://logsapi.com/topics/linux/">Linux logging topic</a> examines host and service context in more detail.</p>
<h2>Keep source time and arrival time separate</h2>
<p>Record when the producer says an event happened and when your collector received it. A buffered event might arrive much later than it occurred. Conversely, an incorrectly configured clock can make a new event appear to come from the future. Store the original timestamp and its timezone information before applying any normalization. Define one display convention for operators, and make the distinction between event time and arrival time visible in incident queries.</p>
<p>Within one process, use a monotonic timer to measure elapsed work when the runtime provides one. Do not subtract arbitrary wall-clock timestamps across different machines to claim precise request durations. Include a boot or process-instance identifier where necessary to distinguish reused process identifiers. Treat apparent ordering across independent systems as evidence to investigate, not automatic proof of causation.</p>
<h2>Specify delivery and checkpoint behavior</h2>
<p>Write down what a successful delivery acknowledgment means. It could mean that a receiver accepted a batch into memory, persisted it to disk, or made it available for queries. These are materially different promises. Advance a collection checkpoint only at the stage your recovery design requires. If a sender retries after an uncertain acknowledgment, the receiving side may see the same event twice.</p>
<p>Choose a stable event identifier or a documented source-position key when you need duplicate detection. Keep retry attempts distinguishable from new business events. An HTTP request retried by a customer can be a new application attempt, even when the logging transport also retries its delivery. Test both scenarios. Avoid claiming exactly-once processing unless the complete path, including failures and recovery, actually enforces it.</p>
<h2>Bound storage and plan for rotation</h2>
<p>Estimate a buffer using measured input rate, average serialized event size, and the outage duration you want to absorb. Leave room for metadata and event bursts. A buffer is a finite resource, so decide what happens when it fills: reject new events, drop selected categories, stop reading, or apply backpressure. Make the chosen behavior observable with counters and alerts. Silent loss turns a useful operational system into a source of false confidence.</p>
<p>For file inputs, test the rotation strategy used by the application or administrator. Renaming a file, replacing it, and truncating it in place can interact differently with a reader's stored position. Restart the collector during rotation and compare produced identifiers with received identifiers. Also test an application that exits halfway through writing a record. Your parser should handle a partial tail without merging unrelated events.</p>
<h2>Reduce sensitive content at the producer</h2>
<p>Prefer event categories and reference identifiers over request bodies, authorization headers, or complete environment dumps. A reverse proxy's URL field can include query parameters, so a seemingly harmless access log may capture credentials or personal information. Keep a documented allowlist of fields and treat changes to it as code changes. Filter before events leave the application where possible, and add collector-side checks as a second layer.</p>
<p>Give collectors the access they need to read approved sources and send to approved destinations. Separate operator access to production events from general development access. If exceptional diagnostic capture is necessary, give it an owner, an expiry, and a narrow scope. Use the principles in <a href="https://logsapi.com/blog/prompt-versioning-and-redaction/">the redaction and versioning guide</a> when logs include AI request context.</p>
<h2>Practice a complete investigation</h2>
<p>Consider a fictional export worker that begins timing out after a release. Start with a failed operation identifier, then find its application attempts and deployment identifier. Check the associated host events for a restart or collection interruption. Compare a successful operation from the same release with one from the preceding release. This sequence turns a large search into a set of specific questions.</p>
<p>A missing completion event has several possible explanations: the operation never finished, the process stopped, the event was filtered, or delivery failed. Inspect collection health before choosing one. Compare source counts with receiver counts over a controlled interval, accounting for deliberate sampling and retry duplicates. Preserve uncertainty in the incident notes rather than filling the gap with a plausible story.</p>
<h2>Validate failure paths and assign ownership</h2>
<p>Before expanding coverage, deliberately interrupt the collector connection, restart the reader, send an invalid record, and exhaust a small test buffer. Verify checkpoint recovery and examine how loss is reported. Include an input containing a secret-shaped test value to check that it never appears downstream. Keep test data synthetic. These exercises are useful because they evaluate observable behavior under failure rather than simply confirming that a normal event can arrive.</p>
<h2>Conclusion</h2>
<p>A dependable server log pipeline has a clear event contract, explicit delivery behavior, bounded resources, and visible collection health. Give its configuration and parsers an owner, review schema changes, and repeat the failure exercises when components change. Start with one important service and prove that an engineer can trace a real operational question through the complete path. Expand only when that path is understandable and its limits are documented.</p>]]></content:encoded>
    </item>
    <item>
      <title>Git and Code Logs: Connect Commits to Deployments</title>
      <link>https://logsapi.com/blog/git-code-ci-audit-logs/</link>
      <guid isPermaLink="true">https://logsapi.com/blog/git-code-ci-audit-logs/</guid>
      <description>Connect repository history, build attempts, artifacts, and release outcomes into an explainable trail of software changes.</description>
      <pubDate>Sun, 20 Sep 2026 00:00:00 GMT</pubDate>
      <category>Developer Operations</category>
      <content:encoded><![CDATA[<p>When a release behaves unexpectedly, a commit message rarely answers every question. You need to know which source revision entered the build, which build attempt produced the artifact, who or what approved the release, and what actually reached the target environment. Git history contributes one part of this story. Continuous integration logs, artifact records, and deployment events contribute the rest.</p>
<p>The goal is an explainable chain of evidence from code to running software. This guide proposes a compact event design for that chain. It does not assume a particular hosting service or pipeline vendor. Start with the <a href="https://logsapi.com/topics/git/">Git logging topic</a> for repository events, then extend the same identifiers into the build and deployment systems you operate.</p>
<h2>Separate repository history from activity history</h2>
<p>A commit represents a source revision and its recorded metadata. Repository hosting activity can describe pushes, pull requests, reviews, permission changes, and automation. Build activity describes execution, while deployment activity describes changes to an environment. Avoid treating these streams as interchangeable. A commit's presence in a repository does not establish that it passed a test or was released.</p>
<p>Similarly, a commit author field should not be treated as sufficient evidence of the person who authorized a production change. Record the authenticated actor from the system performing the relevant action, and distinguish human accounts from service identities. Preserve the source system's event identifier so an investigator can reconcile your normalized event with the originating record. Make the provenance of each assertion clear.</p>
<h2>Choose identifiers that survive the workflow</h2>
<p>Use a repository identifier and the full source commit identifier as the basic source reference. Add a pipeline definition version, workflow run identifier, attempt number, job identifier, and artifact digest as the build proceeds. A branch name helps a human navigate, but it can refer to different revisions over time. Record the resolved commit at execution time instead of relying on the branch name to reconstruct it later.</p>
<p>Define each identifier's scope. A run number may be unique only within a particular workflow or repository. A job label may repeat in a matrix build. Preserve the matrix dimensions, such as operating system and runtime version, when they affect the output. Prefer a composite key you can explain over an opaque identifier assembled differently by every team. Document how a rerun relates to the initial execution.</p>
<h2>Inspect Git metadata without turning it into a feed</h2>
<p>For a local inspection, a compact command is <code>git log -1 --format='%H %cI %s'</code>. It displays the full commit identifier, a strict ISO-style committer date, and the subject. The <a href="https://git-scm.com/docs/git-log">official git-log reference</a> defines these formatting placeholders and the options for selecting history. Use the result to inspect a revision, not as proof that deployment occurred.</p>
<p>For machine ingestion, parse structured metadata with a reliable library or a deliberately delimited format, then serialize it using a JSON encoder. A commit subject is user-controlled text. It may contain characters that break a naive shell command, document, or hand-built JSON string. Avoid collecting complete commit messages and patches into a broadly accessible log index when identifiers and change references answer the operational question.</p>
<h2>Make attempts and outcomes explicit</h2>
<p>Emit separate events for a job being queued, starting, and reaching a terminal state. Distinguish success, failure, cancellation, and skipped work. Measure queue delay separately from execution duration. An unusually long pipeline may be waiting for capacity rather than spending more time running tests. Preserve both the original run identity and the attempt identity when a job is rerun.</p>
<p>For example, GitHub Actions exposes a workflow run identifier that stays the same across reruns and a run-attempt value that increments. Other systems may use different names or scopes. Map those semantics explicitly into your event contract. A later successful attempt should not erase the earlier failure; both are relevant when investigating intermittent tests or repeated manual intervention.</p>
<h2>Identify the artifact that was actually released</h2>
<p>A source commit alone may not uniquely explain a build output. Dependency resolution, build configuration, generated files, and toolchain versions can affect the result. Record the artifact's content digest and the inputs you need to account for that output. Keep dependency manifests, relevant lockfiles, and build configuration versions with the artifact evidence where practical.</p>
<p>Use the same digest when the artifact moves between environments. If your process rebuilds for each environment, record that as a separate build with its own inputs and digest. Do not describe two independently built files as identical solely because they came from the same branch or release label. The <a href="https://logsapi.com/topics/code/">code and delivery logging guide</a> covers useful fields for connecting source changes to runtime evidence.</p>
<h2>Model deployment as a sequence of decisions</h2>
<p>A deployment request and a completed rollout are separate events. Record the target environment, selected artifact, initiator, approval result when relevant, start time, and final outcome. For staged rollouts, preserve the stages and their results. A deployment can partially succeed, so a single success flag may conceal the part of the system that failed to update.</p>
<p>Record a rollback as a new action that names the artifact restored and the reason for the decision. Do not overwrite the original deployment record. Configuration-only changes also deserve an event when they can change behavior. Store a configuration version or approved change reference instead of exposing the complete configuration, which may contain credentials. Correlate release events with service startup events to check what is actually running.</p>
<h2>Protect the evidence and the pipeline</h2>
<p>Build output often contains command arguments, environment details, or data from failing tests. Decide which content is allowed before you stream logs into a shared destination. Avoid unrestricted environment dumps. Use synthetic fixtures in tests and redact sensitive error details close to their source. Secret masking is a useful defensive layer, but it should not be your only reason to print a value.</p>
<p>Treat repository text and external contribution metadata as untrusted input. Store them as data, escape them when displaying them, and never interpolate them into executable commands without an appropriate safe interface. Keep access to release audit records narrow enough to preserve their usefulness. Audit changes to logging configuration and retention, since a change that stops evidence collection can matter as much as an ordinary deployment event.</p>
<h2>Walk through a concrete release investigation</h2>
<p>Imagine an illustrative service release labeled <code>release-24</code> begins returning errors. First, find its deployment completion record and artifact digest. Follow the digest to the producing build attempt, then identify the source commit and configuration version. Check whether the rollout reached all intended instances. This avoids assuming that the newest commit on the main branch represents every running process.</p>
<p>Suppose the first test attempt failed, a rerun passed, and the deployment later rolled back. Keep those three outcomes visible. Compare the failure details with runtime errors, but do not assume they share a cause merely because they occurred near each other. Use the <a href="https://logsapi.com/blog/server-linux-log-pipelines/">server collection pipeline guide</a> to connect release identity with service events and to evaluate gaps in the operational record.</p>
<h2>Test the links before an incident</h2>
<p>Pick one ordinary release and ask a colleague to reconstruct its source, build attempt, artifact, approval, target, and outcome using the recorded identifiers. Include a rerun, a cancellation, and a rollback in the exercise. Verify that each join works without guessing from timestamps or copying a human-readable label. Inspect what happens when an event arrives late or is delivered twice.</p>
<p>Set retention around the investigation period you actually need, and document which evidence expires first. A long-lived deployment index is less useful when its referenced build output has already disappeared. Keep concise provenance records separate from verbose diagnostic output where their access needs or retention periods differ. Review this design when you change the build platform or artifact storage system.</p>
<h2>Conclusion</h2>
<p>Useful Git and code logs connect decisions across the entire release process. Preserve exact revisions, distinguish attempts, identify artifacts by content, and record deployment outcomes as events. Keep sensitive build output controlled and validate the chain with real release exercises. The result is a practical explanation of how a change reached an environment, including the uncertainty and failed attempts that a simple commit list cannot show.</p>]]></content:encoded>
    </item>
    <item>
      <title>iOS and Android Logs: Debug Mobile Apps Responsibly</title>
      <link>https://logsapi.com/blog/ios-android-mobile-logs/</link>
      <guid isPermaLink="true">https://logsapi.com/blog/ios-android-mobile-logs/</guid>
      <description>Design mobile diagnostic events that explain lifecycle and network failures while minimizing personal data and device overhead.</description>
      <pubDate>Sun, 14 Jan 2024 00:00:00 GMT</pubDate>
      <category>Developer Operations</category>
      <content:encoded><![CDATA[<p>Mobile bugs often happen far from a developer's desk. A user changes networks, the app moves to the background, an old build receives a new response shape, or a process stops before work completes. Logs can preserve clues about those transitions. Their value depends on capturing the right context without collecting private content or making the app less reliable.</p>
<p>A useful mobile logging plan defines which questions the team wants to answer, how events relate to a release and operation, and what information must never enter a diagnostic record. This guide covers principles that apply across iOS and Android, while respecting their different logging tools. Begin with a small set of events and validate them in the actual release configuration.</p>
<h2>Start with a debugging question</h2>
<p>Choose a concrete problem, such as an upload that appears to stall. To explain it, you might need the upload's start, network category, retry count, cancellation, completion, and error class. You probably do not need the uploaded file, its original name, or the user's complete profile. Write the investigation question next to every proposed event so the team can challenge fields that do not help answer it.</p>
<p>Separate product analytics from operational diagnostics. Knowing which screen receives the most visits is a different purpose from explaining a failed background task. A single logging stream can blur those purposes and collect more detail than either requires. Define ownership, access, and retention for diagnostic records explicitly, and communicate collection behavior accurately wherever the product describes it.</p>
<h2>Use a compact event contract</h2>
<p>Include an event name, schema version, application version, build identifier, platform, outcome, and a short-lived operation identifier. Add the operating system version when it is relevant to reproducing behavior. Prefer a broad network category over an SSID or precise network location. Use a documented error category instead of an arbitrary exception string that might include personal data.</p>
<p>Keep identifiers narrowly scoped. An identifier created for one upload can join its attempts without becoming a permanent identifier for the person using the app. Document when it expires and whether it can be linked with server records. Pseudonymous identifiers still need care because repeated events can make them informative. The <a href="https://logsapi.com/topics/ios/">iOS logging topic</a> provides a focused starting point for release and lifecycle context.</p>
<h2>Use iOS logging privacy controls deliberately</h2>
<p>Apple's <a href="https://developer.apple.com/videos/play/wwdc2020/10168/">Explore logging in Swift session</a> explains the Logger API, including subsystem and category labels and privacy controls for interpolated values. It describes nonnumeric values such as strings as private by default and demonstrates an explicit public annotation. Treat that annotation as a review decision. A value that seems harmless in a test fixture may contain a customer's information in production.</p>
<p>Use consistent categories for meaningful components, such as synchronization or media processing. Keep personal information out of static message text as well as interpolated values. Do not assume that a platform's default privacy behavior protects a separately implemented remote exporter. Review every output path on its own terms. Avoid promises about how long local messages remain available; collection settings and device conditions affect what can be retrieved.</p>
<h2>Understand what Android Logcat shows</h2>
<p>Android's logging system uses circular buffers, and Logcat exposes messages with priorities and tags. A tag helps narrow a local investigation to a component. A filter changes what the developer sees; it does not by itself remove sensitive data that the application already wrote. Keep production diagnostic content deliberately limited, and verify which logging calls remain in the release build.</p>
<p>On a development device connected through Android Debug Bridge, a command such as <code>adb logcat 'SyncWorker:I *:S'</code> selects informational and higher-priority messages for the illustrative tag <code>SyncWorker</code>. Use a tag that your own app actually emits. The <a href="https://logsapi.com/topics/android/">Android logging guide</a> explains how to structure events around work, process state, and diagnostic output. Local tooling is useful for reproduction, but it is not a durable record of every event.</p>
<h2>Represent asynchronous work as separate events</h2>
<p>A mobile operation can pause, retry, or be canceled as the app's state changes. Give its start and completion records a shared operation identifier, and distinguish individual attempts. Record a terminal outcome when the application can observe one. If the process stops before recording it, leave the operation incomplete rather than inventing a failure result during later analysis.</p>
<p>Record the state that matters to the question, such as foreground or background, without collecting every interaction. A background transition near a network failure is a clue, not proof that the transition caused it. When examining a timeline, separate events observed on the device from events observed on a server. Use correlation identifiers and explicit outcomes to strengthen the explanation.</p>
<h2>Measure elapsed work without trusting every clock</h2>
<p>Keep the event timestamp and the time your receiver ingested it as separate fields. An offline device may submit events much later. A user's wall clock can also be inaccurate or change during a session. Measure an operation's elapsed duration using the platform's appropriate monotonic timing facility, and label the unit clearly in the resulting event.</p>
<p>A server can record its own processing time, but that does not automatically equal the duration seen by the mobile app. Network transfer, retries, and time waiting for a connection can add delay. Compare the measurements as different observations. Do not join unrelated client and server events simply because their timestamps are close. The <a href="https://logsapi.com/blog/server-linux-log-pipelines/">server log pipeline guide</a> explains how collection timing can affect an incident timeline.</p>
<h2>Bound queues, network use, and diagnostic detail</h2>
<p>If the app uploads diagnostic events, set explicit limits on queued bytes, event age, batch size, and retry attempts. Decide what happens when a device remains offline and the queue fills. Dropping low-value diagnostic events may be preferable to consuming unbounded storage, but the policy should be documented. Record aggregate drop counts where practical so a quiet timeline is not mistaken for complete coverage.</p>
<p>Keep collection off latency-sensitive paths where possible, and measure the effect on startup, scrolling, storage, and network usage. Avoid a design that retries immediately forever after an upload failure. Use a bounded retry policy suited to the application and the operating system's scheduling constraints. A logging failure should not silently turn into a user-facing failure of the operation you were trying to observe.</p>
<h2>Review exceptions and diagnostic attachments</h2>
<p>Exceptions can include URLs, file paths, message content, or values passed to a library. Review representative failures with synthetic data instead of assuming that only successful requests contain sensitive information. Normalize predictable error classes and keep free-form details restricted. If a support bundle is necessary, define what it contains, how it is shared, and when it is deleted.</p>
<p>Apply the same scrutiny to screenshots, crash attachments, and local files. A screenshot can expose information that a carefully designed event contract would never include. Build redaction into the source of diagnostic data, then verify the serialized output. Hiding a field in an operator interface is insufficient if it remains present in downloads or another storage destination.</p>
<h2>Preserve the context needed to reproduce a bug</h2>
<p>Keep build identifiers connected to the symbols and mapping files your crash analysis process requires. Record the release channel when it changes the code or configuration that a user receives. Include relevant feature configuration versions without logging confidential values. A device model family or broad capability category can sometimes explain a rendering problem more appropriately than a detailed device fingerprint.</p>
<p>For an illustrative failed upload, a useful record might say that build 42 started operation A, retried after a connection error, moved to the background, and never recorded completion. That evidence supports several reproduction experiments. It does not establish which experiment will reproduce the bug. Preserve those boundaries when turning diagnostic observations into an engineering issue.</p>
<h2>Test the release configuration</h2>
<p>Exercise an offline start, a network change, a cancellation, a process restart, and a queue that reaches its limit. Inspect the actual logs produced by a release build with synthetic credentials and personal-data-shaped values. Confirm that sensitive values are absent, event sizes stay bounded, and operation identifiers connect the expected attempts. Verify that disabling optional diagnostics behaves as the product describes.</p>
<h2>Conclusion</h2>
<p>Responsible mobile logging starts with a precise question and a minimal event contract. Use platform tools thoughtfully, preserve release and operation context, and make queue limits and missing evidence visible. Test privacy and resource behavior in the shipped configuration. A small, understandable set of diagnostic events can help an engineer reproduce a difficult failure while respecting the people and devices running the app.</p>]]></content:encoded>
    </item>
    <item>
      <title>Email, Phone, CRM, and Calendar Logs: Follow the Event</title>
      <link>https://logsapi.com/blog/workspace-crm-event-logs/</link>
      <guid isPermaLink="true">https://logsapi.com/blog/workspace-crm-event-logs/</guid>
      <description>Connect email, phone, CRM, and calendar activity with explicit event identities, channel-specific outcomes, and a workflow you can actually reconstruct.</description>
      <pubDate>Tue, 04 Mar 2025 00:00:00 GMT</pubDate>
      <category>Workspace &amp; Identity</category>
      <content:encoded><![CDATA[<p>A customer asks for a meeting. An email arrives, a workflow creates a CRM activity, a representative calls, and a calendar invitation goes out. When the meeting disappears from the CRM timeline, four separate systems may each report that their own request succeeded. The useful question is not whether a request returned successfully. It is which business event happened, which component observed it, and where the next expected step stopped.</p>
<p>Workspace event logs make those relationships explicit. A practical design preserves the meaning of each channel while adding enough shared context to follow one workflow across applications. Start with a narrow journey, such as creating a meeting from an email, and establish the evidence needed to diagnose it before collecting every available field.</p>
<h2>Separate the event from its delivery</h2>
<p>An event describes something that occurred. A webhook request is one way that description reaches another system. The same event may be delivered several times, and one event may cause several downstream actions. If the log treats every delivery as a new customer action, retries can inflate activity counts and conceal the original failure.</p>
<p>The <a href="https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md">CloudEvents 1.0.2 specification</a> provides a useful reference for an event envelope. It defines required identity, source, type, and specification-version attributes, and an optional event time. Its source-and-ID pairing identifies an event within its source context. Use that distinction when designing your own records; adopting an envelope does not establish delivery guarantees or define your business outcomes.</p>
<p>Keep a separate delivery identifier and attempt number when the transport exposes them. An ingestion record can then say that delivery attempt three carried an event already processed. The business timeline remains one event, while an operational view explains the retries. Neither record has to overwrite the other.</p>
<h2>Choose a small shared envelope</h2>
<p>For an initial design, record an event ID, source system, tenant reference, event type, resource reference, occurrence time, observation time, and workflow correlation ID. Add a schema version so that changed meanings remain distinguishable. These are proposed fields for your application, not a universal provider contract. Document their types, permitted values, and which component assigns them.</p>
<p>Occurrence time describes when the source says the event happened. Observation time describes when your collector received it. Retaining both makes late delivery visible. A correlation ID groups events in one workflow; a causation ID identifies the particular event that prompted another. Do not infer either relationship merely because two records share a customer identifier and nearby timestamps.</p>
<p>Scope resource IDs to the source and tenant that issued them. A short contact ID may be unique inside one account while colliding with another account's contact. A structured reference preserves that boundary. Record the initiating actor separately from the connector's service identity so an automated write does not erase the distinction between user intent and integration execution.</p>
<h2>Preserve what each channel actually means</h2>
<h3>Email: acceptance is one stage</h3>
<p>For email, distinguish a send request, provider acceptance, delivery status, and an application response to an inbound message. A successful API call should not become a claim that a person read the message. Preserve the provider's original status alongside a documented normalized status, and retain an opaque message reference. The <a href="https://logsapi.com/topics/email/">Email Logs API topic guide</a> covers the identity and delivery fields worth considering.</p>
<p>Thread relationships deserve their own treatment. A reply can create a new message while belonging to an existing conversation. Use the source's message and thread references when available; matching subjects alone is a fragile substitute. Keep message bodies, attachment contents, and recipient lists outside general operational logs unless a specific, approved diagnostic requirement justifies them.</p>
<h3>Phone: call state and business outcome differ</h3>
<p>A call can be initiated, ring, connect, and end without the intended customer conversation occurring. Model telephony state separately from outcomes such as appointment agreed or callback requested. One customer interaction can also contain several call legs. Preserve parent-child relationships when your telephony system supplies them, rather than treating every leg as an independent outreach attempt.</p>
<p>Record duration with its definition: elapsed call time and connected duration answer different questions. A duration of zero needs a status to be interpretable. Prefer opaque participant references in broad dashboards. If troubleshooting requires a phone number or recording, retrieve it through an access-controlled source application instead of copying it into every downstream event.</p>
<h3>CRM: describe the committed change</h3>
<p>A CRM update log should identify the object, changed field names, initiating actor, and result. Separate an attempted write from the confirmation that the application accepted the intended update. If your integration reads the object afterward to verify a change, label that observation separately. A later read shows the state then observed, not necessarily every intermediate update.</p>
<p>For synchronization, keep the source record version or revision when available. An older notification should not silently replace newer data. Describe merge and conflict decisions with stable reason codes. The <a href="https://logsapi.com/topics/crm/">CRM event design guide</a> explores how to keep contact, activity, and ownership changes connected without copying the full customer record.</p>
<h3>Calendar: retain instance and time context</h3>
<p>Calendar changes need event identity, action, and relevant recurrence context. Moving one occurrence of a recurring meeting differs from modifying the series. Keep the source's series and instance references where applicable. Distinguish organizer changes from attendee responses, and treat cancellation as its own event rather than an unexplained disappearance from the local view.</p>
<p>Store timestamps with explicit offsets and preserve the calendar's named time zone when interpreting local scheduling rules. All-day events require date semantics rather than an invented midnight appointment. During diagnosis, distinguish the meeting's scheduled time from the time someone edited it. These are different clocks with different meanings.</p>
<h2>Handle duplicates, delay, and missing steps</h2>
<p>Design a deduplication key from documented source identity, tenant scope, and event identity. Choose its retention window to cover the replay and recovery behavior you actually support. If the source lacks a stable event ID, record that limitation and design a scoped substitute carefully. A hash of the entire payload can change when harmless metadata changes, while an overly broad key can erase distinct actions.</p>
<p>Do not order the whole workspace by collector arrival time. Use resource revisions or source sequence numbers where their semantics are documented, and preserve uncertainty otherwise. Introduce a reconciliation job for workflows that must eventually match source state. Reconciliation can discover missing records; it should create an explicit reconciliation observation instead of inventing a historical event you never received.</p>
<p>Set expectations for each workflow transition. An accepted email may require no subsequent CRM event, while a meeting creation workflow may require a calendar result within an agreed operational interval. That interval is a team decision informed by observed behavior, not a universal timeout. Label a missing outcome as overdue or unknown until further evidence resolves it.</p>
<h2>Walk one failure across the boundaries</h2>
<p>Consider a calendar invitation that exists in the calendar but not in the CRM. Begin with the workflow ID. Find the initiating email event, the calendar creation attempt, the accepted calendar result, and the CRM write attempt. If the CRM attempt is absent, inspect the transition between the calendar worker and the next queue. If it exists with a permission error, inspect the integration's authorization and retry decision.</p>
<p>Now consider the same CRM write appearing twice. Compare the business event ID with delivery and processing-attempt IDs. Two deliveries may have produced one correct update; two distinct processing attempts may instead have created duplicate activities. That distinction points to an idempotency defect rather than a customer behavior problem. The <a href="https://logsapi.com/blog/agent-tool-call-tracing/">agent tool-call tracing guide</a> extends this approach when an assistant initiates the workflow.</p>
<h2>Keep the timeline useful and appropriately scoped</h2>
<p>A workspace timeline combines information from systems with different audiences. Preserve tenant boundaries, limit who can join identities across channels, and record the purpose of retained fields. Prefer event summaries over conversation contents. Establish retention and deletion handling for the operational store, and make access to sensitive details a deliberate action.</p>
<p>A useful workspace log answers a concrete question with a traceable sequence: what happened, who or what initiated it, what was attempted next, and which outcome is supported by evidence. Start with that sequence, test duplicate and delayed deliveries, and expand only when a new field resolves a real diagnostic gap.</p>]]></content:encoded>
    </item>
    <item>
      <title>MFA Logs: Design an Authentication Audit Trail</title>
      <link>https://logsapi.com/blog/mfa-authentication-audit-logs/</link>
      <guid isPermaLink="true">https://logsapi.com/blog/mfa-authentication-audit-logs/</guid>
      <description>Build an MFA audit trail that explains challenges, decisions, enrollment, and recovery while keeping authentication secrets out of the record.</description>
      <pubDate>Mon, 18 Aug 2025 00:00:00 GMT</pubDate>
      <category>Workspace &amp; Identity</category>
      <content:encoded><![CDATA[<p>A login screen may show a single success message, but an authentication system has made several decisions along the way. It may verify one credential, require an additional factor, evaluate a challenge, apply a policy, and finally issue a session. Logging only the final message leaves important gaps. Logging the entire request creates another problem by collecting material that could expose the account.</p>
<p>An MFA audit trail should explain the decisions without preserving the secrets used to make them. Its value is a reconstructable journey: what the application requested, what the verifier decided, which policy applied, and what access resulted. The design below is an application logging approach, with example field names that should be adapted to your identity system.</p>
<h2>Model authentication as related events</h2>
<p>Begin with a catalog of transitions. Useful examples include authentication started, factor challenge created, factor verification completed, authentication denied, session issued, and session revoked. Keep each event's meaning narrow. Challenge creation means the verifier initiated a challenge; it does not mean the user saw it, responded, or passed it.</p>
<p>Assign an authentication-attempt reference that survives the journey. Give each challenge a separate reference, because an attempt can involve more than one challenge or factor choice. A verification event should point to the challenge it evaluated. A session-issued event should reference the completed authentication decision, allowing an investigator to distinguish a successful factor check from an actual grant of access.</p>
<p>Record trusted decisions at the component that makes them. A browser event saying that a user clicked an approval button describes interface activity. The verifier's accepted response is stronger evidence about verification. Store these as different event types with their source components, rather than allowing a client-provided status to become the authoritative server outcome.</p>
<h2>Define the fields around an investigation</h2>
<p>For a compact event envelope, consider event ID, occurrence time, observation time, tenant reference, actor reference, attempt reference, challenge reference, event type, outcome, and policy version. Add the responsible service and application release. Preserve a provider event ID when one is supplied. Use explicit missing values so absent evidence is not confused with a successful result.</p>
<h3>Use outcomes that preserve uncertainty</h3>
<p>An outcome should be machine-readable and documented. Examples include accepted, denied, expired, canceled, and unavailable. Add a bounded reason code when appropriate. A factor mismatch, policy denial, and verification-service outage are different conditions. Avoid an unbounded provider error string as the only explanation; normalize it to a useful category and retain carefully selected diagnostic context.</p>
<p>Separate the actor attempting access from an administrator performing recovery. If a service initiates a change on behalf of a person, preserve both identities and their relationship. Use internal references rather than exposing email addresses in every record. The <a href="https://logsapi.com/topics/mfa/">MFA Logs API topic guide</a> provides a starting set of field purposes for this design.</p>
<h2>Record successes as well as failures</h2>
<p>The <a href="https://cheatsheetseries.owasp.org/cheatsheets/Logging_Cheat_Sheet.html">OWASP Logging Cheat Sheet</a> recommends recording authentication successes and failures and warns against directly logging sensitive values such as passwords, access tokens, and primary secrets. Its emphasis on event context is useful here: a failure without its time, source, and interaction reference is difficult to interpret.</p>
<p>Successful verification matters because it can close a sequence that began with repeated failures. It also helps explain legitimate friction: a user may fail one method, select another, and complete authentication. Keep the events in one attempt when that reflects the application's behavior. Treat a later fresh login as a different attempt even if it involves the same account.</p>
<p>A timeout does not establish whether a factor was invalid. An interrupted network response can leave the application uncertain about the verifier's decision. Record the uncertainty, query a supported status mechanism if appropriate, and document how the application decides whether a retry is allowed. Do not convert missing evidence into a false acceptance or an unsupported accusation.</p>
<h2>Include enrollment, changes, and recovery</h2>
<p>The audit trail should extend beyond everyday sign-ins. Track factor enrollment requested, enrollment completed, factor replacement, factor removal, recovery initiated, recovery completed, and relevant administrative overrides. Distinguish a requested change from its committed result. Otherwise, a failed enrollment can appear indistinguishable from a newly active factor.</p>
<p>For sensitive changes, record the policy decision and an opaque reference to the factor affected. Keep factor type separate from factor identity. A record can explain that an authenticator was removed without exposing its secret or detailed credential material. If a change requires another approval, link the approval event and the final action through explicit references.</p>
<h3>Give recovery a distinct trail</h3>
<p>Recovery deserves its own workflow ID and reason categories. Record which approved recovery route was used and which actor authorized the result. Preserve the application state before and after the operation in bounded terms, such as active-factor count or access restriction status. Avoid placing identity documents, support conversation transcripts, or answers to verification questions into the general audit stream.</p>
<h2>Keep secrets out of the path</h2>
<p>Build logging around an allowlist of permitted fields. Do not serialize the complete authentication request and hope a later filter catches everything. Authentication secrets can appear in headers, nested objects, query strings, exception messages, and debug output. Review the complete route from application logger to collector, alert notification, support export, and developer console.</p>
<p>Never include one-time codes, recovery codes, private keys, shared factor secrets, or raw session credentials in routine logs. A failed value is still sensitive. When correlation is necessary, prefer an application-issued reference with no authentication power. Keep any identity mapping in a separate controlled system so the broadly available timeline does not automatically become an account directory.</p>
<p>Use synthetic records to exercise redaction. Include nested fields, unusual capitalization, malformed requests, and errors from dependencies. Inspect the resulting log at the final destination. A safe application record is insufficient if a reverse proxy or exception handler independently captures a sensitive request. The <a href="https://logsapi.com/blog/prompt-versioning-and-redaction/">redaction and versioning guide</a> discusses the same boundary problem for AI inputs.</p>
<h2>Build signals that lead to a clear action</h2>
<p>Start with investigation questions rather than a large collection of alerts. Can an operator identify repeated verification failures within one attempt? Can they distinguish many challenged accounts from one account retrying? Can they see a factor replacement followed by a new session? Define the response to each pattern before deciding its notification threshold.</p>
<p>Use several dimensions carefully: account reference, tenant, source service, factor class, application version, and outcome. An IP address or approximate location may add context, but neither proves a person's identity. Missing client information should remain visible as missing. Avoid treating a shared network, travel, or a new device as conclusive evidence of misuse.</p>
<p>Record why a signal fired and which event IDs contributed. An analyst should be able to inspect that evidence without reconstructing the detection query from memory. Keep alert decisions separate from original authentication facts. If the rule changes, preserve its version so a later reviewer can explain why the same event pattern produced a different notification.</p>
<h2>Verify the trail under operational pressure</h2>
<p>Test successful authentication, failed verification, expiration, user cancellation, provider outage, duplicate delivery, and delayed arrival. Then test enrollment and recovery journeys. For each scenario, check that the event sequence has a clear beginning and an evidence-supported ending. Confirm that the session outcome can be connected to the correct attempt without merging two concurrent logins.</p>
<p>Decide what happens when the logging pipeline is unavailable. Buffering, bounded retries, and explicit loss counters are possible engineering choices, each with tradeoffs. A workflow that requires durable audit evidence may need a different failure policy from a low-risk interface event. Make that policy explicit and test it instead of allowing an accidental dependency on collector availability.</p>
<p>Assign access, retention, and review responsibilities to the audit store. Keep administrative changes to its collection rules visible. During an incident, distinguish an empty query result from proof that no event occurred: collection gaps, timestamp errors, and incomplete retention can all limit the record.</p>
<h2>Make the decision understandable</h2>
<p>A strong MFA audit trail connects challenges, verification decisions, factor changes, and resulting sessions while keeping their credentials outside the log. Establish those relationships first, add bounded context for the investigations you support, and verify the difficult paths. The result is a clearer explanation of account access and a more useful foundation for operational response.</p>]]></content:encoded>
    </item>
    <item>
      <title>Wallet and Tokenized Asset Logs: Track State, Not Secrets</title>
      <link>https://logsapi.com/blog/wallet-tokenized-asset-logs/</link>
      <guid isPermaLink="true">https://logsapi.com/blog/wallet-tokenized-asset-logs/</guid>
      <description>Separate wallet intent, application actions, and blockchain evidence so transaction histories remain understandable through retries and reorganizations.</description>
      <pubDate>Sat, 27 Jan 2024 00:00:00 GMT</pubDate>
      <category>Workspace &amp; Identity</category>
      <content:encoded><![CDATA[<p>A wallet interface can report that a request was submitted while an application still has no evidence that its intended state change occurred. A transaction may be awaiting inclusion, fail during execution, or appear in a block that is later replaced before finality. An application can also misinterpret a contract event even when the underlying blockchain record is correct.</p>
<p>Wallet and tokenized asset logs therefore need several kinds of evidence. Track user intent, application processing, and chain observations separately, then connect them through explicit references. This article focuses on engineering that event trail. Ethereum examples illustrate a concrete record model; other networks have different transaction, event, and finality semantics.</p>
<h2>Separate three layers of activity</h2>
<p>The first layer is application intent. A user requests a transfer, connects a wallet, selects a network, or dismisses a signing prompt. These are interface or application events. They describe the requested action and its local outcome. A connected wallet does not imply that any transaction was signed, and a dismissed prompt should not become a failed on-chain transaction.</p>
<p>The second layer is transaction handling. The application prepares an operation, requests authorization, submits a signed transaction through its chosen infrastructure, or receives a transaction reference. Record each stage with a workflow ID and processing-attempt ID. Keep retries visible; the same workflow may involve more than one submission attempt or a replacement transaction.</p>
<p>The third layer is chain observation. A collector observes a receipt, a contract log, or a relevant state value at a particular block. This evidence has a network and block context. It should not be overwritten by a convenient application label. The <a href="https://logsapi.com/topics/wallet/">Wallet Logs API topic guide</a> explains the useful boundaries between these layers.</p>
<h2>Scope every identity to its context</h2>
<p>Use a network identifier alongside wallet, contract, and transaction references. An address alone is not enough to identify the network context of an event. Preserve the emitting contract address separately from participant addresses and the wallet connected to the interface. These can be different actors with different roles in the same workflow.</p>
<h3>Preserve the coordinates of each observation</h3>
<p>For an observed contract log, retain block hash, transaction hash, and log position along with network identity. This combination helps distinguish a particular observation from a later reorganization or replay. Store the collector's event ID separately. It identifies your record, while chain coordinates explain which evidence that record describes.</p>
<p>Add occurrence or block time when available, plus the collector's observation time. Neither is the time a user first pressed a button unless you recorded that separately. Use a clear schema version, a source-node or provider reference, and the decoder version. Those fields become valuable when investigating whether a discrepancy came from collection, interpretation, or application processing.</p>
<h2>Read receipts and logs as specific evidence</h2>
<p>The <a href="https://ethereum.org/developers/docs/apis/json-rpc/">Ethereum JSON-RPC documentation</a> describes receipt status and the fields carried by log objects, including transaction and block references. It also documents a removed flag for logs affected by a chain reorganization. These fields support an evidence-based event model, but they do not establish the meaning of an application's business operation by themselves.</p>
<p>A successful transaction receipt means execution succeeded at that layer; it does not automatically prove every business expectation was met. Your application still needs to verify the intended contract, operation, and resulting state or relevant events. Conversely, an application-side timeout does not demonstrate on-chain failure. Preserve the transaction reference and reconcile against chain evidence.</p>
<p>Use descriptive states such as submitted, observed in block, execution failed, and confirmation policy satisfied. Define each one in terms of the evidence that permits it. Avoid a single ambiguous success flag that tries to represent interface approval, submission acceptance, execution outcome, and application reconciliation at once.</p>
<h2>Plan for reorganizations and repeated observations</h2>
<p>Before finality, your collector's view of the chain may change. Preserve enough block context to identify which observations belong to a replaced branch. A removal or reconciliation finding should mark the earlier observation as no longer canonical for the current view, while retaining the history needed to explain why an application previously acted on it.</p>
<p>Design downstream projections so they can be corrected. If an observed event changes a displayed balance or activity list, define how a later removal reverses or rebuilds that projection. Do not erase the operational record of the first observation. The history of observation and correction is precisely what an investigation needs.</p>
<h3>Document the confirmation policy</h3>
<p>Choose a confirmation policy appropriate to the network and application, and record which policy version produced the application state. A fixed block count should not be described as universal finality. If a network exposes a finality signal, understand its meaning before using it. Keep the observed chain status distinct from the application's own threshold for taking further action.</p>
<h2>Decode contract events deliberately</h2>
<p>Raw event data needs the correct contract interface and context to become meaningful application fields. Record which interface definition and decoder version you used, especially when a contract can be upgraded. A familiar event name is insufficient evidence that two contracts behave identically. Preserve the emitting address and validate the expected network before accepting a decoded event.</p>
<p>For token quantities, retain the exact integer value and the precision metadata used for display. Avoid introducing floating-point rounding into the underlying record. Treat display symbols as labels, not identifiers. Two assets can use the same symbol, and a symbol does not establish authenticity or the application's intended contract.</p>
<p>Tokenized asset workflows may also include off-chain registry, eligibility, or processing steps. Log those as application events with their own source and evidence references. A contract event does not prove that an unrelated off-chain obligation was fulfilled. The <a href="https://logsapi.com/topics/tokenized/">Tokenized Logs API topic guide</a> develops this distinction between contract evidence and surrounding workflow state.</p>
<h2>Reconcile from durable checkpoints</h2>
<p>A live subscription can make observations available quickly, but the indexer still needs a recovery plan. Maintain a checkpoint that identifies the processed range and relevant block context. After an interruption, resume with a bounded overlap and deduplicate observations using their scoped identities. Do not move the checkpoint beyond work that your own storage has durably accepted.</p>
<p>Make partial batch failures explicit. If decoding succeeds for most records but fails for one contract version, retain a bounded diagnostic reference and a retryable status for that record. A collector should not silently advance as though the whole range were processed. Separate collection coverage from application projection completeness so operators know which layer is behind.</p>
<p>Compare important projections with an authoritative state read at a documented block context where the network supports it. Investigate differences using the same network and block assumptions. A current balance and an earlier event-derived balance can both be internally correct for different points in time. Record the reconciliation target and observation time rather than flattening that discrepancy into a generic error.</p>
<h2>Keep credentials and identity links out of broad logs</h2>
<p>Never log private keys, seed phrases, recovery material, or credentials with signing authority. Avoid dumping wallet requests, provider headers, or raw signed payloads into diagnostic output. Keep a bounded operation description and an opaque internal reference when detailed investigation requires separately controlled evidence. Review exception paths as carefully as normal application logging.</p>
<p>Publicly visible addresses can still reveal sensitive relationships when associated with customers, employees, or internal systems. Restrict access to those associations and collect only what the workflow needs. A shortened address is a display convenience, not an anonymization method. If a dashboard does not need identity linkage, provide a scoped internal reference instead.</p>
<h2>Test the history before depending on it</h2>
<p>Exercise canceled prompts, rejected requests, submission timeouts, failed execution, repeated deliveries, decoder errors, and collector restarts. Use a controlled test environment to simulate a replaced block and verify that the application projection can recover. Include the case where a receipt arrives after the interface has already timed out.</p>
<p>Ask an operator to reconstruct one workflow using only the retained records. They should be able to identify intent, submission attempts, observed chain evidence, interpretation, and the application's final decision. Any step requiring an undocumented assumption exposes a useful design gap. Check that the same exercise reveals no credentials or unnecessary personal information.</p>
<h2>Preserve the difference between intent and evidence</h2>
<p>Wallet logging becomes clearer when every state says who observed it, where it belongs, and what evidence supports it. Keep application intent distinct from chain observations, make corrections traceable, and document the rules used to derive displayed state. This produces a history that remains interpretable when timing, retries, and network state become complicated.</p>]]></content:encoded>
    </item>
    <item>
      <title>About LogsAPI.com | Practical Logging &amp; Observability Guides</title>
      <link>https://logsapi.com/about/</link>
      <guid isPermaLink="true">https://logsapi.com/about/</guid>
      <description>Learn about LogsAPI.com, a practical guide to AI logs, developer operations, workspace events, authentication evidence, and connected systems.</description>
    </item>
    <item>
      <title>Contact LogsAPI.com | Questions, Ideas &amp; Corrections</title>
      <link>https://logsapi.com/contact/</link>
      <guid isPermaLink="true">https://logsapi.com/contact/</guid>
      <description>Contact LogsAPI.com at info@logsapi.com for questions about logging, article suggestions, and specific technical corrections.</description>
    </item>
    <item>
      <title>Editorial Approach | The Signal | LogsAPI.com</title>
      <link>https://logsapi.com/editorial/</link>
      <guid isPermaLink="true">https://logsapi.com/editorial/</guid>
      <description>How LogsAPI.com presents logging guides: investigation-led explanations, explicit assumptions, original examples, and primary technical references.</description>
    </item>
    <item>
      <title>Privacy | Browsing &amp; Contact Information | LogsAPI.com</title>
      <link>https://logsapi.com/privacy/</link>
      <guid isPermaLink="true">https://logsapi.com/privacy/</guid>
      <description>Understand the browsing, illustrative examples, email contact links, hosting requests, and external references included on LogsAPI.com.</description>
    </item>
  </channel>
</rss>
