Skip to content

Commit

Permalink
feat(azure_blob_storage): add tool for writing log files to Azure Blo…
Browse files Browse the repository at this point in the history
…b Storage
  • Loading branch information
fujita-h committed Nov 25, 2024
1 parent 9139cd1 commit 3fdb982
Show file tree
Hide file tree
Showing 2 changed files with 170 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import uuid
from datetime import UTC, datetime
from typing import Any, Union

from azure.core.exceptions import ResourceExistsError
from azure.storage.blob import BlobServiceClient, ContentSettings

from core.tools.entities.tool_entities import ToolInvokeMessage
from core.tools.errors import ToolProviderCredentialValidationError
from core.tools.tool.builtin_tool import BuiltinTool


class WriteLogFileTool(BuiltinTool):
"""
Write log file to Azure Blob Storage
"""

def _invoke(
self, user_id: str, tool_parameters: dict[str, Any]
) -> Union[ToolInvokeMessage, list[ToolInvokeMessage]]:
# Ensure runtime and credentials
if not self.runtime or not self.runtime.credentials:
raise ToolProviderCredentialValidationError("Tool runtime or credentials are missing")

# Get account name
account_name = self.runtime.credentials.get("azure_blob_storage_account_name")
if not account_name:
raise ValueError("Azure Blob Storage connection string is required")

# Get API key
api_key = self.runtime.credentials.get("azure_blob_storage_api_key")
if not api_key:
raise ValueError("Azure Blob Storage API Key is required")

# get container name
container_name = tool_parameters.get("container_name")
if not container_name:
raise ValueError("Container name is required")

# get log string
log_string = tool_parameters.get("log_string")
if not log_string:
raise ValueError("Log file is required")

# get resouce name
resource_name = tool_parameters.get("resource_name", "default")

# get file suffix
file_suffix = tool_parameters.get("file_suffix")
file_suffix_str = f"-{file_suffix}" if file_suffix else ""

# get current time
current_time = datetime.now(UTC)
blob = (
f"{resource_name}/"
f"{current_time.strftime('%Y/%m/%d/%H-%M-%S.%f')}-{uuid.uuid4().hex}"
f"{file_suffix_str}.log"
)

# get stop_on_error flag
stop_on_error = tool_parameters.get("stop_on_error", True)

# create a blob client using the connection string
blob_service_client = BlobServiceClient(
account_url=f"https://{account_name}.blob.core.windows.net", credential=api_key
)

# create container
try:
blob_service_client.create_container(name=container_name)
except ResourceExistsError:
pass
except Exception as exc:
if stop_on_error:
raise ValueError("Failed to create container") from exc
else:
return [
self.create_text_message("Failed to create container"),
self.create_json_message({"error": "Failed to create container"}),
]

# content setting
content_settings = ContentSettings(content_type="text/plain")

# upload file to blob storage
blob_client = blob_service_client.get_blob_client(container=container_name, blob=blob)
try:
blob_client.upload_blob(log_string, content_settings=content_settings)
except Exception as exc:
if stop_on_error:
raise ValueError("Failed to write log") from exc
else:
return [
self.create_text_message("Failed to write log"),
self.create_json_message({"error": "Failed to write log"}),
]

return [
self.create_text_message(f'Log file "{blob}" has been written to container "{container_name}"'),
self.create_json_message({"blob": blob, "container": container_name}),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
identity:
name: write_log_file
author: Hiroshi Fujita
label:
en_US: Write Log File
ja_JP: ログに書き出し
description:
human:
en_US: Write logs to Azure Blob Storage
ja_JP: ログをAzure Blob Storageに書き出し
llm: This tool write logs to Azure Blob Storage
parameters:
- name: log_string
type: string
required: true
label:
en_US: Log contents
ja_JP: ログの内容
human_description:
en_US: SSelect what you want to write to the log.
ja_JP: ログに書き出す内容を選択します。
llm_description: Select what you want to write to the log.
form: llm
- name: container_name
type: string
required: true
label:
en_US: Container name
ja_JP: コンテナ名
human_description:
en_US: Name of the container to upload to
ja_JP: アップロード先のコンテナの名称
llm_description: Name of the container to upload to
form: llm
- name: resource_name
type: string
required: true
label:
en_US: Resource Name
ja_JP: リソース名
human_description:
en_US: The resource name is an identifier to distinguish the log category. A virtual folder with this name will be created just under the container root.
ja_JP: リソース名は、ログのカテゴリを区別するための識別名です。コンテナのルートのすぐ下に、この名前の仮想フォルダで作成されます。
llm_description: The resource name is an identifier to distinguish the log category. A virtual folder with this name will be created just under the container root.
form: llm
default: default
- name: file_suffix
type: string
required: false
label:
en_US: File Suffix
ja_JP: ファイルサフィックス
human_description:
en_US: Blob names are classified into virtual folders by date and time to make them chronologically sortable, and consist of a timestamp and random characters to separate duplicates. You can add any characters to the end of this blob name. The extension .log is automatically added.
ja_JP: Blobの名称は時間軸でソート可能にするために、日時の仮想フォルダに分類され、タイムスタンプと重複を裂けるためのランダムな文字で構成されます。このblob名称の末尾には自由な文字を付与できます。拡張子は自動で.logが付与されます。
llm_description: Blob names are classified into virtual folders by date and time to make them chronologically sortable, and consist of a timestamp and random characters to separate duplicates. You can add any characters to the end of this blob name. The extension .log is automatically added.
form: llm
- name: stop_on_error
type: boolean
required: true
label:
en_US: Stop on Error
ja_JP: エラー時に停止する
human_description:
en_US: Set whether to stop the flow if the file upload fails.
ja_JP: ファイルのアップロードが失敗した場合に、フローを止めるかを設定します。
llm_description: Set whether to stop the flow if the file upload fails.
form: form
default: true

0 comments on commit 3fdb982

Please sign in to comment.