GetContextLogs支持查询指定日志前(上文)后(下文)的若干条日志。

请求语法

GET /logstores/<logstorename>?type=context_log&pack_id=<>&pack_meta=<>&back_lines=<num>&forward_lines=<num> HTTP/1.1
Authorization: <AuthorizationString>
Date: <GMT Date>
Host: <Project Endpoint>
x-log-bodyrawsize: 0
x-log-apiversion: 0.6.0
x-log-signaturemethod: hmac-sha1

请求参数

  • 请求头

    GetContextLogs接口无特有请求头。关于Log Service API的公共请求头,请参见公共请求头

  • 请求元素
    名称 类型 必选 描述
    logstorename string 待查询日志的Logstore名称。
    type string Logstore中数据的类型。在GetContextLogs接口中该参数必须为 context_log。
    pack_id string 起始日志所属的Log Group的唯一标识。
    pack_meta string 起始日志在对应Log Group 内的唯一标识。
    back_lines int 指定起始日志往前(上文)的日志条数,取值范围为 (0, 100]。
    forward_lines int 指定起始日志往后(下文)的日志条数,取值范围为 (0, 100]。

响应参数

  • 响应头

    GetContextLogs接口无特有响应头。关于Log Service API的公共响应头,请参见公共响应头

  • 响应元素

    请求成功,其响应Body包括查询到的日志(可能为空)。

    {
        "total_lines": 201,
        "back_lines": 100,
        "forward_lines": 100,
        "progress": "Complete", 
        "logs": [
            {
                "__index_number__": "-100",
                "__tag__:__pack_id__": "895CEA449A52FE-8c8",
                "__pack_meta__": "0|MTU1OTI4NTExMjg3NTQ2NDU1OA==|4|1",
                ...
            }
        ]
    }
    名称 类型 描述
    total_lines int 返回的总日志条数,包含请求参数中所指定的起始日志。
    back_lines int 向前查询到的日志条数。
    forward_lines int 向后查询到的日志条数。
    progress string 表示查询的结果是否完整,Complete表示完整,其他值为不完整。
    logs array 获取到的日志,按上下文顺序排列。

    logs 中的每一项都是该日志的内容(键值对),除用户日志内容外,还包含如下三个字段。

    名称 类型 描述
    __index_number__ string 该日志在本次查询结果中相对上下文的位置,负数表示上文,0表示起始日志,正数表示下文。例如:-100表示起始日志往前的第100条日志。
    __tag__:__pack_id__ string 该日志所属的Log Group的唯一标识,可作为请求参数中的pack_id进行查询。
    __pack_meta__ string 该日志在所属Log Group内的唯一标识,可作为请求参数中的pack_meta进行查询。
  • 细节描述

    上下文查询的时间范围为起始日志的前后一天。

错误码

除了返回Log Service API的通用错误码,还可能返回如下特有错误码。

HTTP 状态码 ErrorCode ErrorMessage 描述
400 InvalidParameter invalid pack meta/id 请求参数中的packMeta或 packID非法。
400 InvalidParameter back_lines or forward_lines must be postive 请求参数中的backLines或forwardLines非法,至少有一个是正数。

示例

此处以Java SDK为例,请使用0.6.38 及以上版本的Java SDK。

如果您通过logtail文本采集方式采集日志,该方式将自动为日志附加上下文信息。

package sdksample;

import com.aliyun.openservices.log.Client;
import com.aliyun.openservices.log.common.LogContent;
import com.aliyun.openservices.log.common.LogItem;
import com.aliyun.openservices.log.common.QueriedLog;
import com.aliyun.openservices.log.common.TagContent;
import com.aliyun.openservices.log.exception.LogException;
import com.aliyun.openservices.log.request.PutLogsRequest;
import com.aliyun.openservices.log.response.GetContextLogsResponse;
import com.aliyun.openservices.log.response.GetLogsResponse;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class GetContextLogsSample {

    private static int getCurrentTimestamp() {
        return (int) (new Date().getTime() / 1000);
    }

    private static class PackInfo {
        public String packID;
        public String packMeta;

        public PackInfo(String id, String meta) {
            this.packID = id;
            this.packMeta = meta;
        }
    }

    private static PackInfo extractPackInfo(QueriedLog log) {
        PackInfo ret = new PackInfo("", "");
        ArrayList<LogContent> contents = log.GetLogItem().GetLogContents();
        for (int i = 0; i < contents.size(); ++i) {
            LogContent content = contents.get(i);
            if (content.GetKey().equals("__tag__:__pack_id__")) {
                ret.packID = content.GetValue();
            } else if (content.GetKey().equals("__pack_meta__")) {
                ret.packMeta = content.GetValue();
            }
        }
        return ret;
    }

    public static void main(String args[]) throws InterruptedException, LogException {
        String endpoint = "<log_service_endpoint>"; // 选择与 project 所属区域匹配的 Endpoint
        String accessKeyId = "<your_access_key_id>"; // 使用您的阿里云访问密钥 AccessKeyId
        String accessKeySecret = "<your_access_key_secret>"; // 使用您的阿里云访问密钥 AccessKeySecret
        String project = "<project_name>"; // 要查询的 project
        String logstore = "<logstore_name>"; // 要查询的 logstore
        // 构建一个客户端实例
        Client client = new Client(endpoint, accessKeyId, accessKeySecret);

        System.out.println("请确保指定的 logstore 已开启索引");
        Thread.sleep(3000);

        // 使用 GetLogs 并在查询语句中加上 | with_pack_meta 来获取起始日志的 pack_id 和 pack_meta。
        // 查询时间范围:最近 15 分钟。
        // 起始日志:返回结果的第一条。
        String query = "*|with_pack_meta";
        GetLogsResponse response = client.GetLogs(project, logstore,
                (int) getCurrentTimestamp() - 900, (int) getCurrentTimestamp(),
                "", query);
        ArrayList<QueriedLog> logs = response.GetLogs();
        if (logs.isEmpty()) {
            System.out.println("未查询到任何日志");
            System.exit(1);
        }

        // 提取第一条日志的 pack 信息。
        PackInfo info = extractPackInfo(logs.get(0));
        if (info.packMeta.isEmpty() || info.packID.isEmpty()) {
            System.out.println("pack ID: " + info.packID + ", pack meta: " + info.packMeta);
            System.out.println("起始日志的 pack 信息不完整,请确保该日志是通过 logtail 写入的");
            System.exit(1);
        }

        // 使用得到的 pack 信息进行上下文查询(双向查询)。
        GetContextLogsResponse contextRes = client.getContextLogs(project, logstore,
                info.packID, info.packMeta, 10, 10);
        System.out.println("双向查询");
        System.out.println("pack ID: " + info.packID + ", pack meta: " + info.packMeta);
        System.out.println("is complete: " + contextRes.isCompleted());
        System.out.println("total lines: " + contextRes.getTotalLines());
        System.out.println("back lines: " + contextRes.getBackLines());
        System.out.println("forward lines: " + contextRes.getForwardLines());
        Thread.sleep(1000);

        // 使用查询结果中的第一条日志,向前查询上文(单向),至多三次。
        List<QueriedLog> contextLogs = contextRes.getLogs();
        for (int i = 0; i < 3 && !contextLogs.isEmpty(); i++) {
            QueriedLog log = contextLogs.get(0);
            info = extractPackInfo(log);
            GetContextLogsResponse res = client.getContextLogs(project, logstore,
                    info.packID, info.packMeta, 10, 0);
            System.out.println("向前查询上文");
            System.out.println("pack ID: " + info.packID + ", pack meta: " + info.packMeta);
            System.out.println("is complete: " + res.isCompleted());
            System.out.println("total lines: " + res.getTotalLines());
            System.out.println("back lines: " + res.getBackLines());
            System.out.println("forward lines: " + res.getForwardLines());
            contextLogs = res.getLogs();

            Thread.sleep(1000);
        }

        // 使用查询结果中的最后一条日志,向后查询下文(单向),至多三次。
        contextLogs = contextRes.getLogs();
        for (int i = 0; i < 3 && !contextLogs.isEmpty(); i++) {
            QueriedLog log = contextLogs.get(contextLogs.size() - 1);
            info = extractPackInfo(log);
            GetContextLogsResponse res = client.getContextLogs(project, logstore,
                    info.packID, info.packMeta, 0, 10);
            System.out.println("向后查询下文");
            System.out.println("pack ID: " + info.packID + ", pack meta: " + info.packMeta);
            System.out.println("is complete: " + res.isCompleted());
            System.out.println("total lines: " + res.getTotalLines());
            System.out.println("back lines: " + res.getBackLines());
            System.out.println("forward lines: " + res.getForwardLines());
            contextLogs = res.getLogs();

            Thread.sleep(1000);
        }
    }
}