> ## Documentation Index
> Fetch the complete documentation index at: https://docs.coze.cn/llms.txt
> Use this file to discover all available pages before exploring further.

本教程将引导你使用扣子罗盘 Java SDK，完成从 Prompt 准备、代码集成到 Trace 观测的端到端流程，帮助你构建可观测的 AI 应用。
## 步骤一：Prompt 准备 {#0c355200}
在编码之前，需在扣子罗盘平台完成 Prompt 的定义与发布。

1. **创建 Prompt**：在工作空间中新建 Prompt，编写提示词内容并定义变量（如 `{{query}}`）。
2. **获取 Prompt Key**：进入 Prompt 详情页，复制 **Prompt Key**，这是 SDK 调用的唯一凭证。
3. **发布版本**：完成调试后，务必**提交版本**。SDK 仅能拉取已提交版本的 Prompt。建议为版本设置 `label`（如 `production`）以便管理。

## 步骤二：集成 SDK 与上报数据 {#756df8ea}
在 Java 项目中集成 SDK，通过埋点上报 Trace 数据，实现对 AI 应用的全链路监控。
以下示例展示了如何初始化客户端、创建 Root Span 追踪业务流、以及上报 Model Span 记录模型调用详情。
:::tip 说明
* **资源管理**：强烈推荐使用 `try-with-resources` 语句，确保 `CozeLoopClient` 和 `CozeLoopSpan` 在使用后自动关闭，避免内存泄漏和数据丢失。
* **数据刷新**：在短生命周期的应用（如定时任务、CLI 工具）中，程序退出前请显式调用 `client.flush()` 或 `client.close()`，确保缓冲区内的 Trace 数据被立即上报。
:::

```Java
import com.coze.loop.client.CozeLoopClient;
import com.coze.loop.client.CozeLoopClientBuilder;
import com.coze.loop.entity.ExecuteParam;
import com.coze.loop.entity.ExecuteResult;
import com.coze.loop.spec.tracespec.ModelChoice;
import com.coze.loop.spec.tracespec.ModelInput;
import com.coze.loop.spec.tracespec.ModelMessage;
import com.coze.loop.spec.tracespec.ModelOutput;
import com.coze.loop.trace.CozeLoopSpan;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

public class CozeLoopBestPractice {

    public static void main(String[] args) {
        // 在非 Spring Boot 环境中，通过 Builder 手动构建客户端。
        // SDK 会自动从环境变量 COZELOOP_WORKSPACE_ID 和 COZELOOP_API_TOKEN 读取配置。
        try (CozeLoopClient client = new CozeLoopClientBuilder()
                .serviceName("java-best-practice-example")
                .build()) {

            // 1. 创建 Root Span，追踪整个业务流程
            try (CozeLoopSpan rootSpan = client.startSpan("travel_plan_generation", "custom")) {
                rootSpan.setTag("user_id", "user_67890");
                rootSpan.setTag("request_source", "mobile_app");

                // 2. 在业务逻辑中创建 Model Span，用于追踪模型调用
                callLLM(client, "为我推荐一个上海的周末两日游路线");

                // 3. (可选) 执行 Prompt
                executePrompt(client, "your_prompt_key", "你好");

            } finally {
                // 在短生命周期的应用（如脚本）结束前，强制刷新以确保数据上报
                 client.flush();
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 模拟一次大模型调用，并上报一个 Model Span。
     */
    private static void callLLM(CozeLoopClient client, String userInput) {
        // 使用 try-with-resources 自动管理 Span 的生命周期
        try (CozeLoopSpan modelSpan = client.startSpan("llm_call_doubao", "model")) {
            // 设置模型提供商和名称
            modelSpan.setModelProvider("volcengine");
            modelSpan.setModelName("doubao-pro-32k");

            // 准备模型输入
            ModelInput input = new ModelInput();
            input.setMessages(Collections.singletonList(new ModelMessage("user", userInput)));
            modelSpan.setInput(input);

            // ----- 在此处执行你的实际 LLM 调用逻辑 -----
            // String llmResponse = yourLLMApi.chat(userInput);
            String llmResponse = "好的，这是为您规划的上海两日游路线：第一天...";
            int inputTokens = 25;
            int outputTokens = 150;
            // -----------------------------------------

            // 记录模型输出和 Token 消耗
            ModelOutput output = new ModelOutput();
            output.setChoices(
                    Collections.singletonList(
                            new ModelChoice(new ModelMessage("assistant", llmResponse), "stop", 0L)));
            modelSpan.setOutput(output);
            modelSpan.setInputTokens(inputTokens);
            modelSpan.setOutputTokens(outputTokens);
        }
    }

    /**
     * (可选) 执行在 CozeLoop 平台上定义的 Prompt。
     */
    private static void executePrompt(CozeLoopClient client, String promptKey, String query) {
         if (promptKey == null || promptKey.equals("your_prompt_key")) {
             System.out.println("\n提示：请替换 `your_prompt_key` 为你在平台创建的实际 Prompt Key 来测试执行功能。");
             return;
         }
        try (CozeLoopSpan executeSpan = client.startSpan("execute_prompt_example", "custom")) {
            Map<String, Object> variables = new HashMap<>();
            variables.put("query", query); // "query" 是你在 Prompt 中定义的变量名

            ExecuteParam param = ExecuteParam.builder()
                    .promptKey(promptKey)
                    .variableVals(variables)
                    .build();

            // 同步执行 Prompt
            ExecuteResult result = client.execute(param);

            executeSpan.setTag("prompt_key", promptKey);
            executeSpan.setInput(variables);
            if (result.getMessage() != null) {
                executeSpan.setOutput(result.getMessage().getContent());
            }
            if (result.getUsage() != null) {
                executeSpan.setTag("total_tokens", result.getUsage().getTotalTokens());
            }
        }
    }
}
```

## 步骤三：数据观测 {#b1c55265}
代码运行并成功上报后，登录扣子罗盘平台。在 **观测** > **Trace 列表** 页面，你将看到刚刚上报的 Trace 数据。点击详情可查看完整的调用链路视图，平台会自动关联 `rootSpan` 下的子 Span（如 `modelSpan`），帮助你快速定位耗时瓶颈和调试模型效果。
