Skip to content

feat(azure_blob sink): add append blob support via blob_type option - #25627

Open
Danielku15 wants to merge 9 commits into
vectordotdev:masterfrom
Danielku15:feature/append-blob
Open

feat(azure_blob sink): add append blob support via blob_type option#25627
Danielku15 wants to merge 9 commits into
vectordotdev:masterfrom
Danielku15:feature/append-blob

Conversation

@Danielku15

@Danielku15 Danielku15 commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds blob_type: append support to the azure_blob sink, implementing #19397.

The default behavior (blob_type: block) is unchanged. When blob_type: append is set, each flush appends to a stable-named Azure Append Blob rather than creating a new uniquely-named blob per batch — the natural model for continuous log streaming where you want a single growing file per time window.

This branch is forward-merged onto master following the reorganization in #25148 and the tags & metadata feature in #25545. Blob tags and metadata now apply to both block and append blobs: for append mode they are set on the underlying AppendBlobClientCreateOptions when the blob is first created (verified end-to-end by a new integration test).

Key design decisions:

  • Type-aware defaults: blob_time_format defaults to %Y-%m-%d (daily rotation) and blob_append_uuid defaults to false for append, matching the expected continuous-stream use case. Both can still be overridden.
  • EAFP append flow: try append_block first (hot path = 1 API call for an existing blob), create on 404, retry. A 409 Conflict on create is swallowed — a concurrent writer created the blob first. BlockCountExceedsLimit (50k-block cap) and ContainerNotFound produce actionable warnings.
  • Azure hard limit enforcement: batch.max_bytes defaults to the 4 MiB append_block limit when unset (or when only implicitly at the 10 MB bulk default); explicit values above 4 MiB are rejected at startup.
  • Ordering: request.concurrency defaults to 1 for append mode (Azure orders appended blocks by receive-time, so parallel flushes could interleave). Users can still set it explicitly.
  • Delivery: documented as at-least-once, consistent with the rest of Vector; the field docs cross-reference request.retry_attempts = 0 for at-most-once.
  • Compressed append blobs produce concatenated compressed frames (one per batch). Multi-stream decompressors (gunzip, zstd -d) handle these correctly.
  • Tags & metadata applied at blob-creation time for append mode — same configuration surface as block mode.

Vector configuration

Minimal append blob configuration:

sinks:
  my_append_logs:
    type: azure_blob
    inputs: [...]
    connection_string: "DefaultEndpointsProtocol=https;AccountName=...;AccountKey=...;EndpointSuffix=core.windows.net"
    container_name: "logs"
    blob_prefix: "app/"
    blob_type: append
    encoding:
      codec: json

This produces a single blob per day (e.g. app/2024-07-18.log) and appends each batch to it. Defaults are blob_time_format: "%Y-%m-%d", blob_append_uuid: false, batch.max_bytes: 4194304.

Explicit batch size and custom rotation:

sinks:
  my_append_logs:
    type: azure_blob
    inputs: [...]
    connection_string: "..."
    container_name: "logs"
    blob_prefix: "app/"
    blob_type: append
    blob_time_format: "%Y-%m-%d-%H"   # hourly rotation
    batch:
      max_bytes: 2097152              # 2 MiB per block
    encoding:
      codec: json

With tags and metadata (identical surface for block and append):

sinks:
  my_append_logs:
    type: azure_blob
    inputs: [...]
    connection_string: "..."
    container_name: "logs"
    blob_prefix: "app/"
    blob_type: append
    tags:
      Project: Blue
      Environment: prod
    metadata:
      source: vector
    encoding:
      codec: json

Important

SAS tokens need the Add (or Write) permission for blob_type: append, and the Tags permission when tags is configured. See the connection_string field docs for the full permission matrix.

How did you test this PR?

  • Unit tests (cargo test --no-default-features --features sinks-azure_blob sinks::azure_blob): 36 pass. Tests added or updated by this branch:
    • azure_blob_build_request_append_blob_defaults — daily time format, no UUID; bracketed with a clock window to avoid a UTC-midnight flake.
    • azure_blob_build_request_append_blob_with_compression — gzip in append mode.
    • azure_blob_append_blob_stable_name_without_uuid_and_time — stable key across flushes.
    • azure_blob_append_blob_with_uuid_override_generates_unique_keys — explicit UUID override still supported.
    • azure_blob_append_blob_custom_time_format_hourly_rotation — hourly rotation, bracketed with a clock window to avoid an hour-boundary flake.
    • azure_blob_block_blob_request_carries_block_type — block dispatch still works.
    • azure_blob_config_default_blob_type_is_block / _parse_blob_type_append — default + explicit parsing.
    • azure_blob_append_blob_default_max_bytes_succeedsblob_type: append with no batch.max_bytes builds cleanly.
    • azure_blob_append_blob_explicit_oversized_batch_fails_at_startup — > 4 MiB rejected with a max_bytes … exceeds error.
    • azure_blob_append_blob_partial_batch_without_max_bytes_succeeds — regression for the Codex P2 remark: a [batch] table that sets only timeout_secs still gets the 4 MiB append default rather than the 10 MB bulk default.
    • azure_blob_append_blob_rejects_oversized_batch / _accepts_batch_at_limit — direct limit_max_bytes boundary checks.
    • azure_blob_build_request_append_blob_with_tags_and_metadata — cross-feature: tags/metadata propagate through the append-blob request.
  • Integration tests (cargo vdev int test azure, verified locally against Azurite 3.35.0):
    • azure_blob_append_blob_reuses_same_blob[_with_oauth] — two batches land in one blob; content order preserved.
    • azure_blob_append_blob_json_encoding[_with_oauth] — NDJSON content-type + line integrity across flushes.
    • azure_blob_append_blob_default_daily_rotation[_with_oauth] — type-aware defaults resolved end-to-end; blob name contains today's %Y-%m-%d.
    • azure_blob_append_blob_multiple_forced_flushes — small batch.max_bytes forces many blocks; all land in one blob.
    • azure_blob_append_blob_with_tags_and_metadata[_with_oauth] — cross-feature: tags/metadata land on the created append blob (verified via get_blob_tags / get_blob_metadata).

Change Type

  • Bug fix
  • New feature
  • Dependencies
  • Non-functional (chore, refactoring, docs)
  • Performance

Is this a breaking change?

  • Yes
  • No

Does this PR include user facing changes?

  • Yes. Please add a changelog fragment based on our guidelines.
  • No. A maintainer will apply the no-changelog label to this PR.

References

Notes

  • Please read our Vector contributor resources.
  • Do not hesitate to use @vectordotdev/vector to reach out to us regarding this PR.
  • Some CI checks run only after we manually approve them.
    • We recommend adding a pre-push hook, please see this template.
    • Alternatively, we recommend running the following locally before pushing to the remote branch:
      • make fmt
      • make check-clippy (if there are failures it's possible some of them can be fixed with make clippy-fix)
      • make test
  • After a review is requested, please avoid force pushes to help us review incrementally.
    • Feel free to push as many commits as you want. They will be squashed into one before merging.
    • For example, you can run git merge origin master and git push.
  • If this PR introduces changes Vector dependencies (modifies Cargo.lock), please
    run make build-licenses to regenerate the license inventory and commit the changes (if any). More details on the dd-rust-license-tool.

@github-actions github-actions Bot added the domain: sinks Anything related to the Vector's sinks label Jun 15, 2026
@github-actions github-actions Bot added domain: external docs Anything related to Vector's external, public documentation docs review on hold The documentation team reviews PRs only after a PR is approved by the COSE team. labels Jun 15, 2026
@Danielku15

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e5734e634c

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/sinks/azure_blob/config.rs Outdated
Comment thread src/sinks/azure_blob/service.rs
Comment thread src/sinks/azure_blob/service.rs
Comment thread src/sinks/azure_blob/service.rs
Comment thread src/sinks/azure_blob/config.rs Outdated
Comment thread src/sinks/azure_blob/test.rs Outdated
@harshavmb

Copy link
Copy Markdown

Hi @Danielku15 ,

Thanks for this PR. I had to implement custom rsyslog extender for this, good to know that this is being worked up on.
Any rough timeline when you want to make this as an active PR for review? I am happy to test this at my end.

@Danielku15

Copy link
Copy Markdown
Contributor Author

@harshavmb As soon the other PR of mine for azure blob storage tagging is merged, I will update this one and make it ready. Hence it strongly depends on how fast the vector folks are with their reviews. The code is mostly prepared locally already. 😉

@pront pront added type: feature A value-adding code addition that introduce new functionality. sink: azure_blob Anything `azure_blob` sink related labels Jul 13, 2026
Combines the newly-merged tags & metadata support (PR vectordotdev#25545) with the
append-blob feature so that both features coexist:

* Tags/metadata now apply to both `blob_type: block` and `blob_type: append`.
  Append blobs receive the tags/metadata on blob creation via
  `AppendBlobClientCreateOptions::{blob_tags_string, metadata}`.
* Follows the reorganized layout from PR vectordotdev#25148: `AzureBlobRequest`,
  `AzureBlobResponse`, `AzureBlobMetadata`, `AzureBlobRetryLogic` and
  `build_client`/`build_healthcheck` live in `azure_blob::config`;
  `AzureBlobService`/`AzureBlobSink` live in `azure_blob::service`/`sink`.
* `AzureBlobType` moves out of `azure_common::config` (blob-specific) into
  `azure_blob::config` alongside the other blob types.
* Preserves append-only additions: type-aware defaults for
  `blob_time_format`/`blob_append_uuid`, concurrency=1 pin for `Append`,
  `batch.max_bytes` auto-default + startup validation, EAFP append flow
  with `BlockCountExceedsLimit`/`ContainerNotFound` diagnostics, and the
  full unit + integration test coverage plus a new
  `assert_append_blob_with_tags_and_metadata` cross-feature integration
  test.
Aligns with the editorial style the reviewers applied to PR vectordotdev#25545:

* drop the `**Header**:` bold section markers (no other Vector sink
  field uses that pattern),
* remove the compressed-frames paragraph from the field description —
  the same information already lives on the `Append` enum-variant doc
  and therefore in the reference for the `append` value,
* switch "Vector will fail to start" / "pins request concurrency to 1"
  to the passive phrasings used elsewhere ("rejected at startup",
  "defaults `request.concurrency` to `1`"),
* deduplicate "4 MiB"/"4194304" mentions, and reword the batch bullet
  so the append blob key composition is explicit.
@Danielku15

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 894f43c22d

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/sinks/azure_blob/config.rs
Comment thread src/sinks/azure_blob/config.rs
@Danielku15
Danielku15 marked this pull request as ready for review August 9, 2026 15:56
@Danielku15
Danielku15 requested review from a team as code owners August 9, 2026 15:56

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 894f43c22d

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/sinks/azure_blob/service.rs
@pront

pront commented Aug 10, 2026

Copy link
Copy Markdown
Member

@codex fresh review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 894f43c22d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/sinks/azure_blob/config.rs Outdated
Comment thread src/sinks/azure_blob/config.rs Outdated
Comment thread src/sinks/azure_blob/service.rs
…, compression, retry docs)

Rotate append blobs hourly by default (`%Y-%m-%dT%H`, the ISO 8601 reduced-precision
hour form) instead of daily. Azure caps an append blob at 50,000 blocks and each flush
consumes one, so daily rotation capped a partition near 2.3 MiB/s, after which every
append failed with `BlockCountExceedsLimit` until the UTC date changed. Hourly rotation
allows 50,000 flushes per hour, about 56 MiB/s at the 4 MiB batch limit.

Reject `snappy` and `zlib` at startup when `blob_type` is `append`. Each batch is
compressed on its own and appended as a separate block, so the blob only reads back if
concatenated streams decode as a whole: `gzip` (multi-member) and `zstd` (multi-frame)
qualify, Vector's raw Snappy blocks and bare zlib streams do not. zlib is why this is an
error rather than a warning -- standard zlib decoders return only the first block and
report success, so the loss is invisible to the consumer.

Drop the claim that `request.retry_attempts = 0` yields at-most-once delivery. It only
disables the sink-level retry; the batch is failed instead, and upstream retries or a
resending source can still produce duplicates.

Also extract `resolved_blob_naming()` so the `blob_type`-specific naming defaults are
unit-testable without an Azurite round trip.
@Danielku15

Copy link
Copy Markdown
Contributor Author

Remarks addressed

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7d5c6934df

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/sinks/azure_blob/config.rs
…d blobs

A block blob receives one self-contained payload per request, like the other object-store
sinks, so framing the JSON codec as one array per blob is correct there. An append blob
instead accumulates payloads into one growing blob -- the same shape the `file` sink
writes -- and Azure concatenates them with nothing in between, so a second flush left the
blob holding `[...][...]`, which no JSON or NDJSON parser accepts.

Append mode now resolves codec defaults through `SinkType::StreamBased`, the same value
the `file` sink uses, so `codec = "json"` without explicit framing writes newline-delimited
JSON. Only the defaults are `blob_type`-aware: explicitly configured `framing` is passed
through untouched, since delimiters and envelopes are the user's choice to make. The
`blob_type` docs explain the seam behavior so that choice can be an informed one.

Block mode is unchanged and keeps emitting one JSON array per blob.
@Danielku15

Copy link
Copy Markdown
Contributor Author

Failed build of the playground seems unrelated to my changes: "The hosted runner lost communication with the server. Anything in your workflow that terminates the runner process, starves it for CPU/Memory, or blocks its network access can cause this error.". I guess a GitHub outage is to blame here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs review on hold The documentation team reviews PRs only after a PR is approved by the COSE team. domain: external docs Anything related to Vector's external, public documentation domain: sinks Anything related to the Vector's sinks sink: azure_blob Anything `azure_blob` sink related type: feature A value-adding code addition that introduce new functionality.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

AppendBlob support for azure_blob sink

3 participants