All Products
Search
Document Center

Simple Log Service:Correlate log context with PackId

Last Updated:Jun 08, 2026

A contextual query locates logs immediately before and after a target log from a specific source. When you process large volumes of logs, assign a PackId to group related logs for fast, complete context retrieval.

How it works

A PackId follows the format contextual prefix-log group ID, for example, 5FA51423DDB54FDA-1E3:

  • contextual prefix: Uppercase hexadecimal digits, such as 5FA51423DDB54FDA. Logs that share a contextual prefix belong to the same log context.

  • log group ID: Uppercase hexadecimal digits, such as 1E3. Within a log context, the log group ID increments sequentially. For example, 1E3 and 1E4 are adjacent groups.

The client generates a PackId and sends it with the log write request. Simple Log Service groups logs that share a contextual prefix into the same log context.

Automatically generate PackId

  • Logs written by using a producer SDK: Logs from the same producer instance share a context and support contextual queries. The Aliyun Log Java Producer and the C Producer SDK automatically generate and attach a PackId.

  • Logs collected by Logtail: Logtail automatically generates and attaches a PackId. Logs from the same file on the same host or pod share a context and support contextual queries.

Manually generate PackId with the PutLogs API

Parameters

When you call the PutLogs API, include the PackId in the LogTags attribute of the LogGroup in your PutLogs request. Set the Key to __pack_id__:

{
  "Topic": "my-topic",
  "Source": "127.0.0.1",
  "LogTags": [
      {
        "Key": "__pack_id__",
        "Value": "5FA51423DDB54FDA-1"
      },
      {
        "Key": "my_other_tag_key",
        "Value": "my_other_tag_value"
      }
   ],
   "Logs": [
     {
       "Time": 1728961415,
        "Contents": [
            {
              "Key": "hello",
              "Value": "world"
            }
        ]
     }
   ]
}

Sample code

Java example

  1. Add the following dependencies to the pom.xml file.

     <dependency>
        <groupId>com.google.guava</groupId>
        <artifactId>guava</artifactId>
        <version>27.0.1-jre</version>
    </dependency>
    <dependency>
        <groupId>com.aliyun.openservices</groupId>
        <artifactId>aliyun-log</artifactId>
        <version>0.6.111</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>2.0.12</version>
    </dependency>
  2. Run the following code to generate a PackId and upload it through PutLogs. Replace project, logstore, endpoint, accessKeyId, and accessKeySecret with your actual values.

    package org.example;
    import com.aliyun.openservices.log.Client;
    import com.aliyun.openservices.log.common.LogItem;
    import com.aliyun.openservices.log.common.TagContent;
    import com.aliyun.openservices.log.exception.LogException;
    import com.aliyun.openservices.log.request.PutLogsRequest;
    import com.google.common.base.Charsets;
    import com.google.common.hash.Hashing;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import java.lang.management.ManagementFactory;
    import java.net.InetAddress;
    import java.net.NetworkInterface;
    import java.net.SocketException;
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.Enumeration;
    import java.util.List;
    import java.util.concurrent.atomic.AtomicLong;
    public class Main {
        private static final String TAG_PACK_ID = "__pack_id__";
        private static final int TOKEN_LEN = 4;
        public static void main(String[] args) throws LogException {
            System.out.println("Hello world!");
            // Use the same PackIdGenerator instance for the same context.
            PackIdGenerator generator1 = new PackIdGenerator();
            System.out.println(generator1.generateNewPackId());
            System.out.println(generator1.generateNewPackId());
            System.out.println(generator1.generateNewPackId());
            // Use different PackIdGenerator instances for different contexts.
            PackIdGenerator generator2 = new PackIdGenerator();
            System.out.println(generator2.generateNewPackId());
            System.out.println(generator2.generateNewPackId());
            // Configure log parameters.
            String project = "your-project-name";
            String logstore = "your-logstore-name";
            String topic = "your-topic";
            String source = "127.0.0.1";
            Client client = new Client("your-endpoint", "your-access-key-id", "your-access-key-secret");
            List<LogItem> logs = new ArrayList<>();
            LogItem log = new LogItem();
            log.PushBack("hello", "world");
            logs.add(log);
            // Send a log request.
            PutLogsRequest req = new PutLogsRequest(project, logstore, topic, source, logs);
            // Add the PackId to the tag list.
            req.SetTags(Arrays.asList(new TagContent(TAG_PACK_ID, generator1.generateNewPackId())));
            client.PutLogs(req);
            // Send another log request.
            PutLogsRequest req2 = new PutLogsRequest(project, logstore, topic, source, logs);
            req.SetTags(Arrays.asList(new TagContent(TAG_PACK_ID, generator1.generateNewPackId())));
            client.PutLogs(req2);
        }
        public static class NetworkUtils {
            private NetworkUtils() {
            }
            public static boolean isIpAddress(final String ipAddress) {
                if (ipAddress == null || ipAddress.isEmpty()) {
                    return false;
                }
                try {
                    final String[] tokens = ipAddress.split("\\.");
                    if (tokens.length != TOKEN_LEN) {
                        return false;
                    }
                    for (String token : tokens) {
                        int i = Integer.parseInt(token);
                        if (i < 0 || i > 255) {
                            return false;
                        }
                    }
                    return true;
                } catch (Exception ex) {
                    return false;
                }
            }
            public static String getLocalMachineIp() {
                try {
                    Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
                    while (networkInterfaces.hasMoreElements()) {
                        NetworkInterface ni = networkInterfaces.nextElement();
                        if (!ni.isUp()) {
                            continue;
                        }
                        Enumeration<InetAddress> addresses = ni.getInetAddresses();
                        while (addresses.hasMoreElements()) {
                            final InetAddress address = addresses.nextElement();
                            if (!address.isLinkLocalAddress() && address.getHostAddress() != null) {
                                String ipAddress = address.getHostAddress();
                                if ("127.0.0.1".equals(ipAddress)) {
                                    continue;
                                }
                                if (isIpAddress(ipAddress)) {
                                    return ipAddress;
                                }
                            }
                        }
                    }
                } catch (SocketException ex) {
                    // Ignore the exception.
                }
                return null;
            }
        }
        public static class PackIdGenerator {
            private static final Logger LOGGER = LoggerFactory.getLogger(PackIdGenerator.class);
            private static final AtomicLong GENERATORID = new AtomicLong(0);
            private final String packIdPrefix;
            private final AtomicLong batchId = new AtomicLong(0);
            public PackIdGenerator() {
                packIdPrefix = generatePackIdPrefix(GENERATORID.getAndIncrement()).toUpperCase() + "-";
            }
            public String generateNewPackId() {
                return packIdPrefix + Long.toHexString(batchId.getAndIncrement()).toUpperCase();
            }
            private String generatePackIdPrefix(Long instanceId) {
                String ip = NetworkUtils.getLocalMachineIp();
                if (ip == null) {
                    LOGGER.warn("Failed to get local machine ip, set ip to 127.0.0.1");
                    ip = "127.0.0.1";
                }
                String name = ManagementFactory.getRuntimeMXBean().getName();
                String input = ip + "-" + name + "-" + instanceId;
                return Hashing.farmHashFingerprint64().hashString(input, Charsets.US_ASCII).toString();
            }
        }
    }

    Parameters in the sample code

    Parameter

    Description

    Example

    project

    The Simple Log Service project name.

    test-project

    logstore

    The Simple Log Service Logstore name.

    test-logstore

    endpoint

    The Simple Log Service public endpoint. Endpoints.

    cn-hangzhou.log.aliyuncs.com

    accessKeyId

    The AccessKey ID. Create an AccessKey.

    LTAI****************

    accessKeySecret

    The AccessKey secret. Create an AccessKey.

    yourAccessKeySecret

Go example

  1. Install the Go SDK and the protobuf dependency.

    go get -u github.com/aliyun/aliyun-log-go-sdk
    go get google.golang.org/protobuf
  2. Run the following code to generate a PackId and upload it through PutLogs. Replace project, logstore, endpoint, accessKeyId, and accessKeySecret with your actual values.

    package main
    import (
    	"crypto/md5"
    	"fmt"
    	"os"
    	"sync/atomic"
    	"time"
    	sls "github.com/aliyun/aliyun-log-go-sdk"
    	"google.golang.org/protobuf/proto"
    )
    func main() {
    	// Use the same PackIdGenerator instance for the same context.
    	g1 := NewPackIdGenerator()
    	fmt.Println(g1.Generate())
    	fmt.Println(g1.Generate())
    	fmt.Println(g1.Generate())
    	// Use different PackIdGenerator instances for different contexts.
    	g2 := NewPackIdGenerator()
    	fmt.Println(g2.Generate())
    	fmt.Println(g2.Generate())
    	// Configure log parameters.
    	project := "your-project-name"
    	logstore := "your-logstore-name"
    	topic := "your-topic"
    	source := "your-source"
    	client := sls.CreateNormalInterface("your-endpoint", "your-access-key-id", "your-access-key-secret", "")
    	logs := []*sls.Log{
    		{
    			Time: proto.Uint32(uint32(time.Now().Unix())),
    			Contents: []*sls.LogContent{
    				{
    					Key:   proto.String("hello"),
    					Value: proto.String("world"),
    				},
    				{
    					Key:   proto.String("hi"),
    					Value: proto.String("world"),
    				},
    			},
    		},
    	}
    	// Use the PostLogStoreLogsV2 operation to write logs.
    	err := client.PostLogStoreLogsV2(project, logstore, &sls.PostLogStoreLogsRequest{
    		LogGroup: &sls.LogGroup{
    			Topic:  &topic,
    			Source: &source,
    			Logs:   logs,
    			LogTags: []*sls.LogTag{
    				{
    					Key:   proto.String("__pack_id__"), // Add the PackId to the tag list.
    					Value: proto.String(g1.Generate()),
    				},
    			},
    		},
    	})
    	if err != nil {
    		panic(err)
    	}
    	// Use the PutLogs operation to write logs. g1.Generate() creates a new PackId.
    	err = client.PutLogs(project, logstore, &sls.LogGroup{
    		Topic:  &topic,
    		Source: &source,
    		Logs:   logs,
    		LogTags: []*sls.LogTag{
    			{
    				Key:   proto.String("__pack_id__"), // Add the PackId to the tag list.
    				Value: proto.String(g1.Generate()),
    			},
    		},
    	})
    	if err != nil {
    		panic(err)
    	}
    }
    type PackIdGenerator struct {
    	prefix string
    	id     atomic.Uint64
    }
    func NewPackIdGenerator() *PackIdGenerator {
    	return &PackIdGenerator{
    		prefix: generatePackIDPrefix(),
    		id:     atomic.Uint64{},
    	}
    }
    func (g *PackIdGenerator) Generate() string {
    	return fmt.Sprintf("%s-%X", g.prefix, g.id.Add(1))
    }
    // Generate context from the hostname, PID, and time.
    func generatePackIDPrefix() string {
    	m := md5.New()
    	m.Write([]byte(time.Now().String()))
    	hostName, _ := os.Hostname()
    	m.Write([]byte(hostName))
    	m.Write([]byte(fmt.Sprintf("%v", os.Getpid())))
    	return fmt.Sprintf("%X", m.Sum(nil))
    }
    

    Parameters in the sample code

    Parameter

    Description

    Example

    project

    The Simple Log Service project name.

    test-project

    logstore

    The Simple Log Service Logstore name.

    test-logstore

    endpoint

    The Simple Log Service public endpoint. Endpoints.

    cn-hangzhou.log.aliyuncs.com

    accessKeyId

    The AccessKey ID. Create an AccessKey.

    LTAI****************

    accessKeySecret

    The AccessKey secret. Create an AccessKey.

    yourAccessKeySecret

View log context

  1. In your project, click the target logstore. On the raw logs > raw data tab, find the target log and click the Context query icon icon.

    Note

    Logs submitted through PutLogs with the same PackId contextual prefix are grouped into the same log context. Click context view to display log groups that share a contextual prefix, with the target log highlighted.

    Set a time range, such as 15 minutes, and click query / analyze.

  2. Scroll the page to view the context of the selected log.

    In the context view panel, the current log is highlighted. Use older and newer to browse adjacent logs. Select a field from all fields or enter a keyword to highlight matches.

References