Skip to content

Commit 29076ba

Browse files
authored
Adjust fluent-bit logging integration (#3478)
* Move import to the top * Fix double error logging * Add missing backticks
1 parent 811643f commit 29076ba

3 files changed

Lines changed: 13 additions & 17 deletions

File tree

docs/docs/guides/server-deployment.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -229,8 +229,8 @@ Fluent-bit supports two modes depending on how you want to access logs.
229229

230230
=== "Full mode"
231231

232-
Logs are shipped to Fluent-bit and can be read back through the dstack UI and CLI via Elasticsearch or OpenSearch.
233-
Use this mode when you want a complete integration with log viewing in dstack:
232+
Logs are shipped to Fluent-bit and can be read back through the `dstack` UI and CLI via Elasticsearch or OpenSearch.
233+
Use this mode when you want a complete integration with log viewing in `dstack`:
234234

235235
```shell
236236
$ DSTACK_SERVER_FLUENTBIT_HOST=fluentbit.example.com \
@@ -244,7 +244,7 @@ Fluent-bit supports two modes depending on how you want to access logs.
244244
The dstack UI/CLI will show empty logs. Use this mode when:
245245

246246
- You have an existing logging infrastructure (Kibana, Grafana, Datadog, etc.)
247-
- You only need to forward logs without reading them back through dstack
247+
- You only need to forward logs without reading them back through `dstack`
248248
- You want to reduce operational complexity by not running Elasticsearch/OpenSearch
249249

250250
```shell

src/dstack/_internal/server/services/logs/__init__.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from typing import List, Optional
33
from uuid import UUID
44

5+
from dstack._internal.core.errors import ServerClientError
56
from dstack._internal.core.models.logs import JobSubmissionLogs
67
from dstack._internal.server import settings
78
from dstack._internal.server.models import ProjectModel
@@ -105,9 +106,13 @@ def write_logs(
105106

106107

107108
async def poll_logs_async(project: ProjectModel, request: PollLogsRequest) -> JobSubmissionLogs:
108-
job_submission_logs = await run_async(
109-
get_log_storage().poll_logs, project=project, request=request
110-
)
109+
try:
110+
job_submission_logs = await run_async(
111+
get_log_storage().poll_logs, project=project, request=request
112+
)
113+
except LogStorageError as e:
114+
logger.error("Failed to poll logs from log storage: %s", repr(e))
115+
raise ServerClientError("Failed to poll logs from log storage")
111116
# Logs are stored in plaintext but transmitted in base64 for API/CLI backward compatibility.
112117
# Old logs stored in base64 are encoded twice for transmission and shown as base64 in CLI/UI.
113118
# We live with that.

src/dstack/_internal/server/services/logs/fluentbit.py

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from datetime import datetime
12
from typing import List, Optional, Protocol
23
from uuid import UUID
34

@@ -99,7 +100,6 @@ def read(
99100
try:
100101
response = self._client.search(**search_params)
101102
except ElasticsearchError as e:
102-
logger.error("Elasticsearch/OpenSearch search error: %s", e)
103103
raise LogStorageError(f"Elasticsearch/OpenSearch error: {e}") from e
104104

105105
hits = response.get("hits", {}).get("hits", [])
@@ -112,8 +112,6 @@ def read(
112112
message = source.get("message", "")
113113

114114
if timestamp_str:
115-
from datetime import datetime
116-
117115
try:
118116
timestamp = datetime.fromisoformat(timestamp_str.replace("Z", "+00:00"))
119117
except ValueError:
@@ -180,16 +178,10 @@ def write(self, tag: str, records: List[dict]) -> None:
180178
)
181179
response.raise_for_status()
182180
except httpx.HTTPStatusError as e:
183-
logger.error(
184-
"Fluent-bit HTTP request failed with status %d: %s",
185-
e.response.status_code,
186-
e.response.text,
187-
)
188181
raise LogStorageError(
189182
f"Fluent-bit HTTP error: status {e.response.status_code}"
190183
) from e
191184
except httpx.HTTPError as e:
192-
logger.error("Failed to write log to Fluent-bit via HTTP: %s", e)
193185
raise LogStorageError(f"Fluent-bit HTTP error: {e}") from e
194186

195187
def close(self) -> None:
@@ -206,7 +198,6 @@ def write(self, tag: str, records: List[dict]) -> None:
206198
for record in records:
207199
if not self._sender.emit(tag, record):
208200
error = self._sender.last_error
209-
logger.error("Failed to write log to Fluent-bit via Forward: %s", error)
210201
self._sender.clear_last_error()
211202
raise LogStorageError(f"Fluent-bit Forward error: {error}")
212203

@@ -271,7 +262,7 @@ def __init__(
271262
index=es_index,
272263
api_key=es_api_key,
273264
)
274-
logger.debug(
265+
logger.info(
275266
"Fluent-bit log storage initialized with Elasticsearch/OpenSearch reader"
276267
)
277268
else:

0 commit comments

Comments
 (0)