# Gegen Podman debuggen

> Die DataBridge lokal mit Breakpoints gegen die Podman-Testumgebung debuggen — konkret in Rider, Visual Studio und VS Code, inklusive Steuerung von GetChanges/Process*QueueItems und Einblick in den Service-Bus-Emulator.

---

Site [llms.txt](/llms.txt)

---

Voraussetzung ist die [Podman-Testumgebung](../../lokale-testumgebung/). Der `databridge`-Container
würde sonst Port 7062 belegen, deshalb startet `up.sh`/`up.ps1` alles außer der DataBridge selbst:




<ul class="nav nav-tabs" id="tabs-0" role="tablist">
  <li class="nav-item">
      <button class="nav-link active"
          id="tabs-00-00-tab" data-bs-toggle="tab" data-bs-target="#tabs-00-00" role="tab"
          data-td-tp-persist="windows (powershell)" aria-controls="tabs-00-00" aria-selected="true">
        Windows (PowerShell)
      </button>
    </li><li class="nav-item">
      <button class="nav-link"
          id="tabs-00-01-tab" data-bs-toggle="tab" data-bs-target="#tabs-00-01" role="tab"
          data-td-tp-persist="linux / macos" aria-controls="tabs-00-01" aria-selected="false">
        Linux / macOS
      </button>
    </li>
</ul>

<div class="tab-content" id="tabs-0-content">
    <div class="tab-body tab-pane fade show active"
        id="tabs-00-00" role="tabpanel" aria-labelled-by="tabs-00-00-tab" tabindex="0">
        <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-powershell" data-lang="powershell"><span style="display:flex;"><span>dev\up.ps1 -HostMode mssql <span style="color:#66d9ef">process</span>
</span></span></code></pre></div>
    </div>
    <div class="tab-body tab-pane fade"
        id="tabs-00-01" role="tabpanel" aria-labelled-by="tabs-00-01-tab" tabindex="0">
        <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>dev/up.sh --host mssql process
</span></span></code></pre></div>
    </div>
</div>


`--host` (bzw. `-HostMode`) lässt sich mit allen anderen Argumenten kombinieren (Datenbanken,
Mocks, `getchanges`, `process`, `servicebus`) und startet alles außer dem `databridge`-Container
selbst (dafür gibt es das Profil `databridge`, das sonst automatisch aktiv ist). Der Befehl
generiert zusätzlich
`src/DataBridge/local.settings.json` aus der Vorlage `dev/local.settings.dev.json` (Azurite über
`UseDevelopmentStorage=true`, Service-Bus-Emulator über `localhost` statt über den
Compose-Servicenamen `servicebus`, sowie die Toggles aus `dev/.env`, siehe
[GetChanges/Process*QueueItems steuern](#getchangesprocessqueueitems-steuern)).

> **Überschreibt local.settings.json bei jedem Aufruf**
>
> `src/DataBridge/local.settings.json` wird bei **jedem** `--host`/`-HostMode`-Aufruf neu erzeugt und
> dabei kommentarlos überschrieben — auch echte Zugangsdaten, die dort für
> [Cloud-Debugging](../cloud/) eingetragen waren, sind danach weg. Wer beides abwechselnd nutzt,
> siehe [Podman- und Cloud-Settings parallel halten](../cloud/#podman--und-cloud-settings-parallel-halten).



Damit die Connections in Azurite ebenfalls auf den Host statt auf die Compose-Servicenamen
zeigen, setzt `--host`/`-HostMode` beim Seed-Container `DATABRIDGE_RUNTIME=host` (sonst
`container`); `seed.py` ersetzt dann `mssql`/`postgres`/`mysql`/`oracle`/`wiremock` durch
`localhost` mit dem passenden Host-Port aus `dev/.env`.

Zum Zurückwechseln auf den Container-Betrieb reicht ein Aufruf ohne `--host`/`-HostMode` — das
generiert `local.settings.json` nicht neu, startet aber wieder den `databridge`-Container auf
demselben Port. Die generierte Datei vorher löschen oder ignorieren, sie wird nicht mehr gelesen,
solange kein lokaler Prozess läuft.

## In der IDE starten

Alle drei IDEs nutzen dasselbe Projekt `src/DataBridge/DataBridge.csproj` und dasselbe Profil
`DataBridge` aus `src/DataBridge/Properties/launchSettings.json` (startet mit `--port 7062`, passend
zum MCP-Endpoint und zu `curl`-Aufrufen gegen `localhost:7062`).

> **Das richtige Run-Profil auswählen**
>
> Rider (und die anderen IDEs) legen für jede Testklasse bzw. jeden Testfall automatisch eine eigene
> Run-/Debug-Konfiguration an, sobald man einmal über die Gutter-Icons einen Test gestartet hat —
> z. B. „OpenApiConnectorAuthTests“. Diese Konfigurationen bleiben oben im Auswahlmenü stehen und
> werden schnell mit dem eigentlichen Funktions-Profil **DataBridge** verwechselt, gerade wenn Rider
> zuletzt einen Test als aktive Konfiguration gemerkt hat. Startet man versehentlich eine
> Test-Konfiguration statt **DataBridge**, laufen die Unit-Tests statt der Function App —
> sichtbar u. a. daran, dass Breakpoints in Connectoren/Services nicht mehr halten oder plötzlich
> Exceptions aus `DataBridge.Test.*` im Log auftauchen, die eigentlich von einem Test erwartet
> werden (z. B. `ServiceClient_WithoutCredentials_ThrowsNotSupported`). Vor dem Debuggen also immer
> kurz prüfen, dass oben rechts wirklich **DataBridge** (Projekt-Icon, nicht Test-Icon) ausgewählt
> ist.



**Rider**

1. Lösung `src/DataBridge.slnx` öffnen (falls noch nicht offen).
2. Oben rechts das Run-Profil **DataBridge** auswählen (Rider erkennt das Azure-Functions-Projekt
   automatisch und bietet das Profil aus `launchSettings.json` an).
3. Auf das Käfer-Symbol (Debug) statt Play klicken, oder <kbd>Shift</kbd>+<kbd>F9</kbd>.
4. Breakpoints wie gewohnt im Editor setzen (z. B. in `ProcessQueueMessageService` oder einem
   Connector).

**Visual Studio**

1. `src/DataBridge.slnx` öffnen, `DataBridge` als Startprojekt setzen (Rechtsklick im
   Projektmappen-Explorer → *Als Startprojekt festlegen*, falls nicht schon aktiv).
2. Im Dropdown neben dem grünen Play-Pfeil das Profil **DataBridge** wählen.
3. <kbd>F5</kbd> (Debuggen starten) statt <kbd>Ctrl</kbd>+<kbd>F5</kbd>.
4. Breakpoints wie gewohnt setzen.

**VS Code**

VS Code braucht die Azure Functions Core Tools (`func`) und die Erweiterung *Azure Functions*
(oder *C# Dev Kit*), um Attach/Debug über `launchSettings.json` anzubieten. Ohne Erweiterung reicht
auch der direkte Weg:

1. Terminal in `src/DataBridge` öffnen.
2. `func start` (nutzt automatisch `local.settings.json` und den Port aus `host.json`/der
   Umgebung — bei Bedarf `func start --port 7062` explizit angeben).
3. Mit der Erweiterung *C# Dev Kit*: **Debug: Attach to .NET Process** ausführen und den laufenden
   `func`-/`dotnet`-Prozess auswählen. Mit der *Azure Functions*-Erweiterung genügt stattdessen
   <kbd>F5</kbd> direkt im Projektordner, das startet `func start` automatisch im Debug-Modus.
4. Breakpoints wie gewohnt setzen.

Danach in jeder IDE:

- Der MCP-Server `databridge-dev` aus `.mcp.json` funktioniert unverändert
  (`http://localhost:7062/api/mcp?code=local`) — `func start` prüft den Function Key nicht, siehe
  [MCP für die Testumgebung](../../mcp-testumgebung/).
- Eine Anfrage auslösen (z. B. `POST http://localhost:7062/api/ExecuteJob?code=local`, per Bruno,
  `curl` oder MCP `run_job`) und der Breakpoint hält an.

## Logging

`dev/local.settings.dev.json` setzt kein `APPLICATIONINSIGHTS_CONNECTION_STRING` — es gibt also
auch im Host-Modus keine Application Insights, an die etwas gesendet werden könnte. Alles, was die
DataBridge loggt, geht direkt in die Konsole des lokalen Prozesses:

- **Rider:** das *Run*-Fenster (bzw. *Debug*-Fenster mit Breakpoints) am unteren Rand.
- **Visual Studio:** das *Ausgabefenster* (Ansicht → Ausgabe, Quelle „Debug“) sowie bei
  <kbd>F5</kbd> das Konsolenfenster der Function-Host-Runtime.
- **VS Code:** das Terminal, in dem `func start` läuft, bzw. der *Debug Console*-Tab bei Attach.

`src/DataBridge/host.json` setzt für die Kategorien `DataBridge` und `Function` den Log-Level
`Trace` — dieselbe ausführlichste Stufe wie im Container (siehe
[Lokale Testumgebung → Logging](../../lokale-testumgebung/#logging)). Weil hier keine
Application Insights mitläuft, spielen die dortigen Sampling-/Puffer-Regeln
(`TELEMETRY_INFO_SAMPLE_RATE`, `TELEMETRY_CONTROL`) keine Rolle — sie wirken nur auf den Versand
an Application Insights, nicht auf die Konsolenausgabe.

## GetChanges/Process*QueueItems steuern

Zwei unabhängige Schalter entscheiden, ob im Host-Modus etwas automatisch verarbeitet wird:

| Schalter | Argument bei `up.sh --host`/`up.ps1 -HostMode` | Wirkung |
|---|---|---|
| `DATABRIDGE_GETCHANGES` | `getchanges` | `AzureWebJobs.GetChanges.Disabled` in der generierten `local.settings.json` |
| `DATABRIDGE_PROCESS` | `process` | `AzureWebJobs.Process{Standard,High,Low}PriorityQueueItems.Disabled` |




<ul class="nav nav-tabs" id="tabs-3" role="tablist">
  <li class="nav-item">
      <button class="nav-link active"
          id="tabs-03-00-tab" data-bs-toggle="tab" data-bs-target="#tabs-03-00" role="tab"
          data-td-tp-persist="windows (powershell)" aria-controls="tabs-03-00" aria-selected="true">
        Windows (PowerShell)
      </button>
    </li><li class="nav-item">
      <button class="nav-link"
          id="tabs-03-01-tab" data-bs-toggle="tab" data-bs-target="#tabs-03-01" role="tab"
          data-td-tp-persist="linux / macos" aria-controls="tabs-03-01" aria-selected="false">
        Linux / macOS
      </button>
    </li>
</ul>

<div class="tab-content" id="tabs-3-content">
    <div class="tab-body tab-pane fade show active"
        id="tabs-03-00" role="tabpanel" aria-labelled-by="tabs-03-00-tab" tabindex="3">
        <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-powershell" data-lang="powershell"><span style="display:flex;"><span>dev\up.ps1 -HostMode mssql <span style="color:#66d9ef">process</span>             <span style="color:#75715e"># Verarbeitung an, Timer aus</span>
</span></span><span style="display:flex;"><span>dev\up.ps1 -HostMode mssql getchanges <span style="color:#66d9ef">process</span>  <span style="color:#75715e"># beides an</span>
</span></span><span style="display:flex;"><span>dev\up.ps1 -HostMode mssql                     <span style="color:#75715e"># beides aus – Verarbeitung nur manuell per ExecuteJob</span>
</span></span></code></pre></div>
    </div>
    <div class="tab-body tab-pane fade"
        id="tabs-03-01" role="tabpanel" aria-labelled-by="tabs-03-01-tab" tabindex="3">
        <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>dev/up.sh --host mssql process              <span style="color:#75715e"># Verarbeitung an, Timer aus</span>
</span></span><span style="display:flex;"><span>dev/up.sh --host mssql getchanges process   <span style="color:#75715e"># beides an</span>
</span></span><span style="display:flex;"><span>dev/up.sh --host mssql                      <span style="color:#75715e"># beides aus – Verarbeitung nur manuell per ExecuteJob</span>
</span></span></code></pre></div>
    </div>
</div>


Beide Toggles aktivieren automatisch das Profil `servicebus` (siehe
[Service Bus](../../lokale-testumgebung/#service-bus)), weil ohne Emulator weder `GetChanges` noch
`Process*QueueItems` sinnvoll etwas zu tun hätten. Die Durable-Functions-Kette
(`StartGetChangesOrchestration`, `GetChangesOrchestrator`, `GetChangesActivity`, `JobState`) bleibt
immer deaktiviert.

Weil `local.settings.json` bei jedem `--host`-Aufruf neu generiert wird, reicht ein erneutes
`up.sh --host …` mit anderen Toggles, um umzuschalten — die IDE muss dafür neu gestartet werden
(Azure-Functions-Runtime liest `local.settings.json` nur beim Start).

**Typischer Ablauf, um einen Job Ende-zu-Ende mit Breakpoints zu verfolgen:**

1. `dev/up.sh --host mssql process` (Windows: `dev\up.ps1 -HostMode mssql process`) — Datenbank,
   Verarbeitung und Service-Bus-Emulator, aber ohne Container-DataBridge.
2. In der IDE debuggen starten (s. o.), Breakpoint z. B. in `ProcessQueueMessageService` setzen.
3. Job manuell per `ExecuteJob` auslösen — Details, Job-Namen-Muster und Beispielaufruf unter
   [Lokale Testumgebung → Einen Job manuell ausführen](../../lokale-testumgebung/#einen-job-manuell-ausführen-executejob).
   `IsActive: true` ist dafür **nicht** nötig.
4. `getchanges` zusätzlich nur nötig, wenn der Timer selbst (statt `ExecuteJob`) die Änderungen
   erkennen soll — dann muss der Job vorher per `update_job` auf `IsActive: true` gesetzt werden.

## Service Bus einsehen

Drei Wege, in den Service-Bus-Emulator hineinzuschauen, ohne selbst Code zu schreiben:

**Web-Oberfläche `servicebus-explorer` (empfohlen, auch zum aktiven Testen).** Läuft automatisch
mit, sobald das Profil `servicebus` aktiv ist (also auch über `getchanges`/`process`) — kein
separater Start nötig. Zeigt Queues, Nachrichtenzahlen (aktiv/dead-lettered) und einzelne
Nachrichten inkl. Body in einer grafischen Oberfläche:

```text
http://localhost:8090   (Port konfigurierbar über SERVICEBUS_EXPLORER_PORT in dev/.env)
```

Es handelt sich um das Community-Tool
[Service-Bus-Emulator-Explorer](https://github.com/tombiddulph/Service-Bus-Emulator-Explorer) von
Tom Biddulph (nicht von Microsoft, kein Bestandteil des offiziellen Emulators) — als eigener
Container `servicebus-explorer` im Compose-Stack mitgeliefert, per fertigem Image
(`ghcr.io/tombiddulph/service-bus-emulator-explorer`), spricht intern mit `servicebus` über dieselben
Connection-Strings wie die DataBridge selbst.

Anders als die MCP-Diagnose-Tools kann die Web-Oberfläche auch **selbst Nachrichten auf eine Queue
oder ein Topic legen** (eigener Body, Content-Type, Custom Properties, Session-ID) — praktisch, um
`Process*QueueItems` gezielt mit einer handgebauten Nachricht zu testen, ohne vorher `GetChanges`
über einen echten Job laufen zu lassen.

**MCP (kein zusätzliches Werkzeug nötig, gut für Automatisierung/Scripting).** Der MCP-Server
`databridge-dev` bietet schreibgeschützte Diagnose-Tools: `list_queue_statuses`/`get_queue_status`
(Nachrichtenzahlen je Queue) und `peek_*` für die Metadaten wartender Nachrichten (u. a.
Body-Größe, keine Inhalte — siehe [MCP für die Testumgebung](../../mcp-testumgebung/)). Das läuft
über den Admin-Client auf Port 5300, den `ServiceBusService` beim Emulator automatisch anhängt
(siehe [Service Bus](../../lokale-testumgebung/#service-bus)).

**Rohes REST/AMQP, z. B. per `curl`.** Die Management-API des Emulators liegt auf
`http://localhost:5300`; für eigene Skripte, die weder die Weboberfläche noch MCP nutzen sollen,
reicht derselbe Connection-String wie oben.

> **Klassischer Service Bus Explorer funktioniert nicht**
>
> Das weit verbreitete Desktop-Tool *Service Bus Explorer* (Community-Tool von Paolo Salvatori)
> unterstützt den Emulator **nicht** — er ist kein vollwertiger Service-Bus-Namespace und hat andere
> Auth-Mechanismen. Der oben verlinkte `servicebus-explorer` ist eigens für den Emulator gebaut.



> **Für den Alltag reicht MCP**
>
> Für die üblichen Fragen beim Debuggen — „ist die Nachricht überhaupt auf der Queue angekommen?“,
> „wie viele Nachrichten liegen in `sbqignored`?“ — reichen die MCP-Diagnose-Tools. Die
> Web-Oberfläche lohnt sich, sobald man Nachrichten manuell anschauen, **selbst verschicken** oder
> erneut zustellen will — die MCP-Tools sind bewusst rein lesend (siehe
> [MCP-Server](/docs/mcp-server/)) und können das nicht.
