Skip to content

feat(observability): logging foundations (bootstrap, bridge, sanitizer) - #5375

Open
Ma77Ball wants to merge 1 commit into
apache:mainfrom
Ma77Ball:obs/pr1/foundations
Open

Ma77Ball wants to merge 1 commit into
apache:mainfrom
Ma77Ball:obs/pr1/foundations

Conversation

@Ma77Ball

@Ma77Ball Ma77Ball commented Jun 5, 2026 •

Copy link
Copy Markdown
Contributor

What changes were proposed in this PR?

In one sentence: The OpenTelemetry foundation every later observability PR builds on: off by default and opt-in, and anything leaving the process is validated or bounded first.

Plumbing only. No dashboards, no metrics instrumentation, no API changes.


The three pieces

Component Job
OtelInit The single entry point. Reads its OTEL_* settings from observability.conf, validates them, builds the SDK, registers it globally.
TexeraOtelLogAppender A Logback appender that mirrors app logs into OTel. A thin shim, all security logic lives in the sanitizer.
LogSanitizer Pure functions: redact secrets, strip control chars, cap size, drop noisy MDC keys (and redact credential-named ones) before anything ships.

How a log record flows

flowchart TD
    A["logger.info(...)"] --> B[Logback ROOT]
    B --> C["console / file (always)"]
    B --> D{appender bound?}
    D -- no --> E[no-op]
    D -- yes --> F[LogSanitizer]
    F --> G["strip ctrl chars · redact secrets · cap 16K chars · filter MDC"]
    G --> H[OTLP exporter] --> I[collector]
Loading

If the appender is not bound (init off or not yet run), logs still flow to stdout/file untouched.


Bootstrap, and how it stays safe

flowchart TD
    A[Service.run] --> B{OTEL_SDK_DISABLED == false?}
    B -- no --> C[INFO, no-op]
    B -- yes --> D{endpoint valid?\nscheme + host allowlist}
    D -- no --> E[one WARN, no-op]
    D -- yes --> F[build SDK · attrs passthrough, service.name locked]
    F --> G[attach appender · shutdown hook]
Loading
  • Default OFF. Inert until explicitly enabled with OTEL_SDK_DISABLED=false; while disabled no exporters start and nothing is emitted (per [Observability] OpenTelemetry logging foundations (SDK bootstrap, log bridge, sanitizer) #5367).
  • Fails quietly, never crashes. Missing collector or bad config gives one WARN and a no-op, never a startup exception.
  • No autoconfigure SPI, on purpose: filtering must run before any exporter is built, so we read every OTEL_* setting ourselves through observability.conf (HOCON defaults with ${?OTEL_*} overrides).

The reason it is its own PR: every output is validated or bounded

Guard Blocks
Endpoint scheme + host allowlist exfiltration to arbitrary protocols/hosts (scheme is http/https only; extend hosts via TEXERA_OTEL_ALLOWED_HOSTS)
Resource-attribute service.name lock env overriding the service identity every record is keyed by (other attributes pass through)
MDC deny-list + credential-key redaction noisy bridge fields and secret-named values reaching exports
Secret redaction Bearer tokens, password=, AWS keys printed in logs (message and stack trace)
Control-char strip CR/LF log forging from user strings
Body cap (16K chars via MaxBodyChars) + metric-interval fallback runaway log lines / busy-loop exporter

Exception stack traces are appended to the log body, so Dropwizard 500s stay diagnosable from the dashboard instead of vanishing behind "Error handling a request: <id>".


Supporting wiring

  • OTel 1.50.0 deps pinned once in the common/observability module; every service inherits them via dependsOn(Observability).
  • One-line OtelInit.init(...) added to each service entry point.
  • The five OTEL_* knobs are exposed through observability.conf, EnvironmentalVariable, and the single-node .env + k8s values.yaml so operators can find and tune them.
  • Framework log caps (pekko, iceberg, hadoop, kafka, jetty, ...) pinned at WARN so future TRACE/DEBUG surfaces Texera code, not the framework firehose.

Any related issues, documentation, or discussions?

Closes: #5367
Part of #4070. Approach: #5355

How was this PR tested?

  • Unit specs for all three components: LogSanitizerSpec (redaction, stripping, truncation, MDC deny-list + credential-key redaction), OtelInitSpec (endpoint validation, resource-attribute passthrough with service.name protected, interval fallback, default-off, in-memory exporter), TexeraOtelLogAppenderSpec (throwable-body redaction, severity mapping, MDC handling), plus ObservabilityConfigSpec for the config defaults.
  • sbt scalafmtCheckAll passes and the Config + Observability modules compile; full compile and tests run in CI.

Was this PR authored or co-authored using generative AI tooling?

Co-authored with Claude Opus 4.8 in compliance with ASF policy.

@codecov-commenter

codecov-commenter commented Jun 5, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 78.07018% with 50 lines in your changes missing coverage. Please review.
✅ Project coverage is 92.54%. Comparing base (b143a4f) to head (f00c152).
⚠️ Report is 4 commits behind head on main.

Files with missing lines Patch % Lines
...ala/org/apache/texera/observability/OtelInit.scala 70.86% 25 Missing and 12 partials ⚠️
...e/texera/observability/TexeraOtelLogAppender.scala 78.04% 2 Missing and 7 partials ⚠️
...org/apache/texera/observability/LogSanitizer.scala 92.50% 0 Missing and 3 partials ⚠️
.../scala/org/apache/texera/service/FileService.scala 0.00% 1 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##               main    #5375      +/-   ##
============================================
- Coverage     92.60%   92.54%   -0.06%     
- Complexity     5043     5060      +17     
============================================
  Files          1252     1256       +4     
  Lines         53587    53814     +227     
  Branches       6673     6717      +44     
============================================
+ Hits          49623    49802     +179     
- Misses         2315     2343      +28     
- Partials       1649     1669      +20     
Flag Coverage Δ
access-control-service 77.44% <100.00%> (+0.06%) ⬆️
agent-service 99.16% <ø> (ø)
amber 87.97% <77.92%> (-0.12%) ⬇️
computing-unit-managing-service 60.52% <100.00%> (+0.03%) ⬆️
config-service 87.50% <100.00%> (+0.12%) ⬆️
file-service 81.45% <0.00%> (-0.09%) ⬇️
frontend 96.59% <ø> (+<0.01%) ⬆️
notebook-migration-service 83.77% <100.00%> (+0.03%) ⬆️
pyamber 98.58% <ø> (ø)
workflow-compiling-service 74.25% <100.00%> (+0.15%) ⬆️

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions github-actions Bot added the platform Non-amber Scala service paths label Jun 5, 2026
@github-actions

github-actions Bot commented Jun 12, 2026 •

Copy link
Copy Markdown
Contributor

⚠️ Benchmark changes need a look

🟢 2 better · 🔴 6 worse · ⚪ 7 noise (<±5%) · 0 without baseline

Compared against main be65bf8 benchmarked on this same runner, so the delta is largely free of cross-runner hardware noise. The "7d avg" column still reflects the gh-pages dashboard. Treat <±5% as noise unless repeated.

Dashboard · Run

config throughput MB/s latency max Δ latest / 7d
🔴 bs=10 sw=10 sl=64 393 0.24 24,657/30,096/30,096 us 🔴 -9.8% / 🔴 +126.2%
🔴 bs=100 sw=10 sl=64 779 0.475 124,447/164,661/164,661 us 🔴 +7.2% / 🔴 +76.5%
⚪ bs=1000 sw=10 sl=64 907 0.553 1,105,156/1,163,201/1,163,201 us ⚪ within ±5% / 🔴 -30.3%
Baseline details

Latest main be65bf8 from same runner

config metric PR latest main 7d avg Δ latest Δ 7d
bs=10 sw=10 sl=64 throughput 393 tuples/sec 435 tuples/sec 983 tuples/sec -9.7% -60.0%
bs=10 sw=10 sl=64 MB/s 0.24 MB/s 0.266 MB/s 0.6 MB/s -9.8% -60.0%
bs=10 sw=10 sl=64 p50 24,657 us 23,360 us 10,903 us +5.6% +126.2%
bs=10 sw=10 sl=64 p95 30,096 us 33,184 us 13,539 us -9.3% +122.3%
bs=10 sw=10 sl=64 p99 30,096 us 33,184 us 16,174 us -9.3% +86.1%
bs=100 sw=10 sl=64 throughput 779 tuples/sec 834 tuples/sec 1,259 tuples/sec -6.6% -38.1%
bs=100 sw=10 sl=64 MB/s 0.475 MB/s 0.509 MB/s 0.769 MB/s -6.7% -38.2%
bs=100 sw=10 sl=64 p50 124,447 us 116,067 us 86,981 us +7.2% +43.1%
bs=100 sw=10 sl=64 p95 164,661 us 157,126 us 93,289 us +4.8% +76.5%
bs=100 sw=10 sl=64 p99 164,661 us 157,126 us 105,695 us +4.8% +55.8%
bs=1000 sw=10 sl=64 throughput 907 tuples/sec 931 tuples/sec 1,300 tuples/sec -2.6% -30.2%
bs=1000 sw=10 sl=64 MB/s 0.553 MB/s 0.568 MB/s 0.793 MB/s -2.6% -30.3%
bs=1000 sw=10 sl=64 p50 1,105,156 us 1,075,155 us 854,105 us +2.8% +29.4%
bs=1000 sw=10 sl=64 p95 1,163,201 us 1,134,756 us 901,686 us +2.5% +29.0%
bs=1000 sw=10 sl=64 p99 1,163,201 us 1,134,756 us 924,532 us +2.5% +25.8%
Raw CSV
config_idx,batch_size,schema_width,string_len,num_batches,total_ms,total_tuples,total_bytes,tuples_per_sec,mb_per_sec,lat_p50_us,lat_p95_us,lat_p99_us
0,10,10,64,20,508.66,200,128000,393,0.240,24657.02,30096.18,30096.18
1,100,10,64,20,2567.45,2000,1280000,779,0.475,124446.66,164661.36,164661.36
2,1000,10,64,20,22058.79,20000,12800000,907,0.553,1105156.22,1163201.27,1163201.27

@github-actions

github-actions Bot commented Jun 23, 2026 •

Copy link
Copy Markdown
Contributor

Automated Reviewer Suggestions

Based on the git blame history of the changed files, we recommend the following reviewers:

  • Committers with relevant context: @parshimers
    You can request their reviews formally with /request-review @parshimers.

  • Contributors with relevant context: @bobbai00, @aicam, @xuang7
    You can notify them by mentioning @bobbai00, @aicam, @xuang7 in a comment.

@Ma77Ball

Copy link
Copy Markdown
Contributor Author

/request-review @zuozhiw

@github-actions
github-actions Bot requested a review from zuozhiw June 27, 2026 00:32
@Ma77Ball

Copy link
Copy Markdown
Contributor Author

/request-review @Yicong-Huang

@github-actions
github-actions Bot requested a review from Yicong-Huang June 27, 2026 00:32
@Ma77Ball
Ma77Ball marked this pull request as ready for review June 27, 2026 00:33

@Yicong-Huang Yicong-Huang left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

First round of comments: mainly on architecture

Comment thread common/config/src/main/scala/org/apache/texera/observability/LogSanitizer.scala Outdated
Comment thread common/config/build.sbt Outdated
Comment thread common/config/build.sbt Outdated
Ma77Ball added a commit to Ma77Ball/texera that referenced this pull request Jul 7, 2026
  - Move OtelInit, TexeraOtelLogAppender, and
  LogSanitizer (plus specs) from
    common/config into a new common/observability
  module; OTel deps are
    declared once there and each service that calls
  OtelInit.init now
    depends on Observability explicitly.
  - Revert common/config/build.sbt to its pre-PR
  state, dropping the
    incidental scalatest bump (back to 3.2.15).
  - notebook-migration-service never inits OTel, so it
  no longer bundles
    the OTel jars (LICENSE-binary reverted).
  - Document why AllowedMdcKeys forwards only Texera
  correlation IDs and
    what gets dropped.
  - Add Observability/jacoco to the CI coverage job.
@github-actions github-actions Bot added the ci changes related to CI label Jul 7, 2026
@Ma77Ball
Ma77Ball requested a review from Yicong-Huang July 7, 2026 06:39
@Ma77Ball

Copy link
Copy Markdown
Contributor Author

@zuozhiw, can you do a review?

@zuozhiw zuozhiw left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Approve the PR but left some comments. Please take a look and we can have a discussion.

From my perspective I don't really care about flow charts or architecture diagrams, I care more like what API does this provide to developers when they want to add logging, tracing, and metrics. So if there's a description of that it would be nice, if I missed it please let me know.

Also I only see a logging class being added. There are some trace and metrics related config, are we going to expose them as well?

@zuozhiw

zuozhiw commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Approve the PR but left some comments. Please take a look and we can have a discussion.

From my perspective I don't really care about flow charts or architecture diagrams, I care more like what API does this provide to developers when they want to add logging, tracing, and metrics. So if there's a description of that it would be nice, if I missed it please let me know.

Also I only see a logging class being added. There are some trace and metrics related config, are we going to expose them as well?

Ok I now see the trace and metrics related stuff are in second PR, I'll continue to review that.

Ma77Ball added a commit to Ma77Ball/texera that referenced this pull request Jul 16, 2026
…rough + 30s scrape

Switch MDC and resource-attribute filtering from allow-list to deny-list
so new correlation keys need no code edit (zuozhiw review):

- LogSanitizer: replace AllowedMdcKeys with DeniedMdcKeys. Pass every
key through except Pekko's noisy bridge keys, and run surviving values
through sanitize() so secret-shaped content is still redacted.

- OtelInit: buildResource now passes every OTEL_RESOURCE_ATTRIBUTES key
through, keeping only service.name protected from override.

- OtelInit: drop the default metric export interval from 60s to 30s for
higher resolution.
Update LogSanitizerSpec and OtelInitSpec to cover the new behavior.
@zuozhiw

zuozhiw commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

I think this PR is in a good shape and it's good to merge @Ma77Ball

@Ma77Ball

Ma77Ball commented Aug 4, 2026 •

Copy link
Copy Markdown
Contributor Author

Thank you, @zuozhiw, for the review. I will continue working on the other observability PRs. @Yicong-Huang, do you want to do a second pass, or can this be merged?

@Yicong-Huang Yicong-Huang left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔴 5 must-fix · 2 advisory · 2 polish — solid foundation; four gaps CI on this head cannot see, plus a default that contradicts the issue it closes.

Correctness (3)

  • TexeraOtelLogAppender.scala:85 — stack traces bypass secret redaction (must-fix, see inline)
  • OtelInit.scala:52 — grpc:// passes the allowlist but the OTLP exporter throws, aborting startup (must-fix, see inline)
  • TexeraOtelLogAppenderSpec.scala:149 — this spec fails on the head; the deny-list exports secret/password MDC keys (must-fix, see inline)

Design & architecture (1)

  • OtelInit.scala:156 — the five OTEL_* knobs reach no .conf, no EnvironmentalVariable entry and no deploy file, while the SDK is on by default (must-fix, see inline)

Conventions (2)

  • Closing issue #5367 specifies default-off and "remains inert"; this PR ships default-on — flip the default or update the issue (must-fix)
  • Description: the OTel deps are not in the Config module — they live in common/observability, and services use dependsOn(Observability) (advisory)

Simplifications (1)

  • OtelInit.scala:58 — "::1" is unreachable; URI.getHost returns [::1] for the bracketed form (advisory, see inline)

Polish: 2 quick touch-ups (see inline comments).

Verification trace

Two load-bearing claims were checked against reality rather than docs. (1) The grpc:// crash: decompiled the pinned 1.50.0 jars — OtlpGrpcSpanExporterBuilder.setEndpoint delegates to ExporterBuilderUtil.validateEndpoint, which throws IllegalArgumentException for any scheme other than http/https, and the builder call at OtelInit.scala:184 sits outside any Try, so it escapes init() into run(). (2) The MDC gap: ran Observability/testOnly ...TexeraOtelLogAppenderSpec on JDK 17 — 7 passed, 1 failed with Set("secret", ..., "password", ...) contained element "secret", confirming key-named secrets are exported rather than dropped.

@github-actions github-actions Bot added the infra label Aug 12, 2026
@Ma77Ball
Ma77Ball requested a review from Yicong-Huang August 12, 2026 20:19
@Ma77Ball
Ma77Ball force-pushed the obs/pr1/foundations branch 2 times, most recently from 31d76c6 to be75c16 Compare August 12, 2026 21:01

@Yicong-Huang Yicong-Huang left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔴 9 resolved · 0 open · 9 new — every round-1 finding fixed at the source, not papered over. What's left is one theme: this feature's fan-out is missing three legs.

Design & architecture (5)

  • amber/src/main/resources/web-config.yml:48 — TexeraWebApplication and NotebookMigrationService never call OtelInit.init (must-fix, see inline)
  • bin/k8s/values.yaml:363 — values-development.yaml is missing all five OTEL_* entries (must-fix, see inline)
  • OtelInit.scala:174 — the "never throws" contract has no top-level guard, and this read runs even when the SDK is disabled (must-fix, see inline)
  • OtelInit.scala:395 — a ROOT-attached appender re-exports the exporter's own failure logs (must-fix, see inline)
  • TexeraOtelLogAppender.scala:84 — the stack trace ships as body text, not as exception.* attributes (advisory, see inline)

Correctness (1)

  • OtelInit.scala:351 — clampIntervalMs has no test, and its bounds constants were widened for tests that don't exist (must-fix, see inline)

Conventions (1)

  • Description advertises four things the diff lacks: a resource-attribute allowlist, interval-fallback tests, init in every service, and a byte-based body cap (must-fix)

Polish: 2 quick touch-ups (see inline comments).

Verification trace

The log-feedback claim rests on third-party behavior, so I checked it. In the pinned OTel 1.50.0 jars, BatchLogRecordProcessor$Worker and ThrottlingLogger both reference java/util/logging, so export-failure diagnostics go to JUL — and org.slf4j.jul-to-slf4j is on every service's classpath (all six LICENSE-binary files), purely to install the bridge. That closes the path from a failed export back into the ROOT-attached appender.

The values-development.yaml omission was confirmed structurally: sorting both files' texeraEnvVars name lists yields 30 identical names, with these five as the only difference. That is why it reads as an oversight, not a slimmer dev profile.

Sub-classifying the nine new findings into newly-introduced vs. my own late catches was not possible — the prior review's head e69ca7a1 was force-pushed away and is no longer fetchable — so none are attributed either way.

Comment thread amber/src/main/resources/web-config.yml
Comment thread bin/k8s/values.yaml
Comment thread common/observability/build.sbt Outdated

@Yicong-Huang Yicong-Huang left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🚫 Merge conflict with main — no review was performed on this revision.

This PR cannot merge in its current state, so its diff is not the change that would land. Please merge or rebase onto main, resolve the conflict, and re-request review.

@Yicong-Huang

Copy link
Copy Markdown
Contributor

This PR currently conflicts with the base branch.

@Yicong-Huang

Copy link
Copy Markdown
Contributor

This PR conflicts with its base branch and needs to be rebased before review can continue.

@Ma77Ball
Ma77Ball force-pushed the obs/pr1/foundations branch 3 times, most recently from c5ee452 to 1ebcf66 Compare September 11, 2026 10:33

@Yicong-Huang Yicong-Huang left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🚫 Merge conflict with main — no review was performed on this revision.

This PR cannot merge in its current state, so its diff is not the change that would land. Please merge or rebase onto main, resolve the conflict, and re-request review.

@Yicong-Huang Yicong-Huang left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🚫 Merge conflict with main — no review was performed on this revision.

This PR cannot merge in its current state, so its diff is not the change that would land. Please merge or rebase onto main, resolve the conflict, and re-request review.

@Yicong-Huang Yicong-Huang left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🚫 Merge conflict with main — no review was performed on this revision.

This PR cannot merge in its current state, so its diff is not the change that would land. Please merge or rebase onto main, resolve the conflict, and re-request review.

@Ma77Ball Ma77Ball closed this Oct 7, 2026
@Ma77Ball
Ma77Ball force-pushed the obs/pr1/foundations branch from 2ea65b9 to 2cd44ee Compare October 7, 2026 09:11
@Ma77Ball Ma77Ball reopened this Oct 7, 2026
@Ma77Ball
Ma77Ball force-pushed the obs/pr1/foundations branch from 45ed6c7 to c310922 Compare October 8, 2026 22:21
@Ma77Ball
Ma77Ball requested a review from Yicong-Huang October 8, 2026 22:22

@Yicong-Huang Yicong-Huang left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 8 resolved · 1 open · 1 new (1 new = 0 newly introduced · 1 late catches)

Conventions (2)

  • OtelInit.scala:324: description claims a resource-attribute allowlist the code does not implement (advisory, see inline)
  • NotebookMigrationService.scala:65: service config lacks the framework log caps the other services got (advisory, see inline)
Verification trace

Traced the three core components against the tree: OtelInit.buildResource applies every parsed OTEL_RESOURCE_ATTRIBUTES entry as passthrough (only service.name is protected), confirming the allowlist claim in the description is inaccurate. Confirmed all eight services now call OtelInit.init and the other eight web-config yamls carry the framework log caps; the notebook-migration-service config is the outlier.

* here; the one exception is service.name, which the argument controls
* and env cannot override.
*/
private[observability] def buildResource(serviceName: String, rawAttrs: String): Resource = {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Advisory:

The description's guard table still claims a "Resource-attribute allowlist". buildResource applies every parsed OTEL_RESOURCE_ATTRIBUTES entry as passthrough (per the earlier review discussion), protecting only service.name from override. The table should say passthrough, not allowlist. (The same table's "Body cap (16 KiB)" is also slightly off: the cap is 16384 chars via MaxBodyChars, not bytes.)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes, that description is outdated. Thanks for pointing this out. I will fix it shortly.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed the description. The guard table now says resource attributes pass through (only service.name is locked), not "allowlist", and the body cap reads "16K chars via MaxBodyChars" instead of "16 KiB". Updated the matching mermaid node and the test-coverage line too.

configuration: NotebookMigrationServiceConfiguration,
environment: Environment
): Unit = {
org.apache.texera.observability.OtelInit.init("notebook-migration-service")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Advisory:

This service now runs OtelInit.init, so its logs reach the collector, but notebook-migration-service-web-config.yaml lacks the framework log caps (org.apache.pekko, io.grpc, etc. at WARN) that the other eight service configs carry. Without them, a TRACE or DEBUG TEXERA_SERVICE_LOG_LEVEL forwards the framework firehose to the OTel backend. Add the same caps the other configs got when they landed.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Added the same WARN log caps (org.apache.pekko, io.grpc, etc.) to notebook-migration-service-web-config.yaml that the other eight services have, so a DEBUG/TRACE log level no longer forwards the framework firehose to the collector.

Introduce the OpenTelemetry foundation for Texera: an SDK bootstrap, a
Logback-to-OTel log bridge, and a log sanitizer, wired into every service
entry point. This is PR 1 of the observability stack; it ships logging only,
with the trace and metric exporters wired but not yet emitted (those arrive in
follow-up PRs).

New module (common/observability):
- OtelInit: one-call SDK bootstrap per service. Reads OTEL_* settings from
  observability.conf, validates the OTLP endpoint (scheme + host allowlist)
  before any exporter is built, wires the span/log/metric providers explicitly
  (no sdk-extension-autoconfigure), clamps the metric export interval, and
  attaches the log appender to the Logback ROOT logger. The whole init body is
  guarded so a missing or malformed config returns None with one WARN instead
  of throwing into a service's run(), even when telemetry is disabled.
- TexeraOtelLogAppender: bridges Logback events to OTel log records. Maps
  severity, forwards MDC, sets exception.type/message/stacktrace semantic
  attributes, and drops records from io.opentelemetry loggers so export-failure
  diagnostics are not fed back to the collector that just failed.
- LogSanitizer: strips C0 control characters, redacts secrets, and caps body
  length (MaxBodyChars) to keep individual records bounded.

Config (common/config):
- observability.conf with the OTEL_* defaults, ObservabilityConfig to read it,
  and ENV_OTEL_* entries in EnvironmentalVariable.

Wiring:
- build.sbt defines the Observability module and adds dependsOn(Observability)
  to the eight Dropwizard services.
- Each service entry point calls OtelInit.init with its own service name, and
  each service config gains a logging block.

Deployment:
- OTEL_* env entries in bin/single-node/.env, bin/k8s/values.yaml, and
  bin/k8s/values-development.yaml (kept a name-for-name mirror).
- LICENSE-binary manifests updated with the pinned OTel 1.50.0 jars.

Tests: OtelInitSpec, TexeraOtelLogAppenderSpec, LogSanitizerSpec, and
ObservabilityConfigSpec cover endpoint validation, interval clamping,
severity/MDC/exception mapping, self-diagnostic filtering, redaction, and
truncation.

Rebased onto current main.
@Ma77Ball
Ma77Ball force-pushed the obs/pr1/foundations branch from c310922 to f00c152 Compare October 9, 2026 02:50
@Ma77Ball
Ma77Ball requested a review from Yicong-Huang October 9, 2026 03:02

This branch has not been deployed

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

Labels

ci changes related to CI common dependencies Pull requests that update a dependency file engine infra platform Non-amber Scala service paths

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Observability] OpenTelemetry logging foundations (SDK bootstrap, log bridge, sanitizer)

4 participants