Access Method | Data path | Recommended Scenario |
OTLP/HTTP Standard Direct Transmission | Application > Standard OTLP HTTP Exporter > CLS | Recommended as the first choice for manual integration. Suitable for scenarios such as new projects, quick trials, wanting to reduce custom code, and wanting to report traces according to OpenTelemetry standard semantics. |
topic_id header, field mapping, time unit, exit flush, and verification instructions. It also supports multi-dimensional analysis based on reported data, including error diagnosis, performance, Token cost, and user sessions.Parameter | Description |
CLS_DEFAULT_REGION | The region where the Agent application is located, for example, ap-guangzhou. For more information, see Regions and Access Domains. |
TENCENTCLOUD_SECRET_ID | Tencent Cloud access credential SecretId. |
TENCENTCLOUD_SECRET_KEY | Tencent Cloud access credential SecretKey. |
Use the Tencent Cloud Agent Observability Access Assistant Skill.https://skillhub.cn/skills/tencentcloud-cls-agent-obsHelp me connect my current project to Tencent Cloud Agent Observability.Access Method: LangfuseRegion: ap-guangzhou (Replace with your actual region)
CLS_TOPIC_ID below)..env file in your application project. Ensure that .env is added to .gitignore to prevent key leakage.CLS_DEFAULT_REGION=ap-guangzhouCLS_TOPIC_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxTENCENTCLOUD_SECRET_ID=AKIDxxxxxxxxTENCENTCLOUD_SECRET_KEY=xxxxxxxxSERVICE_NAME=my-llm-app# Required for Python only. The Langfuse Python SDK checks whether the secret key exists upon startup. You can fill in any non-empty placeholder value here.LANGFUSE_PUBLIC_KEY=pk-placeholderLANGFUSE_SECRET_KEY=sk-placeholder
CLS_ENDPOINT. The Endpoint is automatically constructed from CLS_DEFAULT_REGION.Log Topic Region | Public Network Endpoint | Private Network Endpoint |
Guangzhou | ap-guangzhou.cls.tencentcs.com | ap-guangzhou.cls.tencentyun.com |
Shanghai | ap-shanghai.cls.tencentcs.com | ap-shanghai.cls.tencentyun.com |
Beijing | ap-beijing.cls.tencentcs.com | ap-beijing.cls.tencentyun.com |
Singapore | ap-singapore.cls.tencentcs.com | ap-singapore.cls.tencentyun.com |
https://{CLS_DEFAULT_REGION}.cls.tencentcs.com/v1/traces.npm install @langfuse/tracing @langfuse/otel @langfuse/openai \\@opentelemetry/sdk-node \\@opentelemetry/exporter-trace-otlp-http \\dotenv
instrumentation.ts.import "dotenv/config";import { NodeSDK } from "@opentelemetry/sdk-node";import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";import { LangfuseSpanProcessor } from "@langfuse/otel";const secretId = process.env.TENCENTCLOUD_SECRET_ID!;const secretKey = process.env.TENCENTCLOUD_SECRET_KEY!;const region = process.env.CLS_DEFAULT_REGION!;const topicId = process.env.CLS_TOPIC_ID!;const auth = Buffer.from(`${secretId}:${secretKey}`).toString("base64");export const sdk = new NodeSDK({spanProcessors: [new LangfuseSpanProcessor({exporter: new OTLPTraceExporter({url: `https://${region}.cls.tencentcs.com/v1/traces`,headers: {Authorization: `Basic ${auth}`,topic_id: topicId,},}),flushAt: 512,flushInterval: 5000,}),],});sdk.start();process.on("SIGTERM", async () => {await sdk.shutdown();});
instrumentation.ts at the top of your business entry file. Ensure that this import precedes modules such as OpenAI and LangChain, which are patched by instrumentation.import { sdk } from "./instrumentation";import OpenAI from "openai";import { observeOpenAI } from "@langfuse/openai";import { startActiveObservation, propagateAttributes } from "@langfuse/tracing";const openai = observeOpenAI(new OpenAI());async function chat(userMessage: string) {return startActiveObservation("chat", async (span) => {span.update({ input: [{ role: "user", content: userMessage }] });return propagateAttributes({ userId: "u-123", sessionId: "s-456", tags: ["model:gpt-4o"] },async () => {const res = await openai.chat.completions.create({model: "gpt-4o",messages: [{ role: "user", content: userMessage }],});span.update({ output: res.choices[0].message });return res;},);});}await chat("Hello");await sdk.shutdown();
pip install langfuse opentelemetry-sdk opentelemetry-exporter-otlp python-dotenv
instrumentation.py. This file must be imported before any langfuse module.import osimport base64from dotenv import load_dotenvfrom opentelemetry import tracefrom opentelemetry.sdk.resources import Resourcefrom opentelemetry.sdk.trace import TracerProviderfrom opentelemetry.sdk.trace.export import BatchSpanProcessorfrom opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporterload_dotenv()secret_id = os.environ["TENCENTCLOUD_SECRET_ID"]secret_key = os.environ["TENCENTCLOUD_SECRET_KEY"]region = os.environ["CLS_DEFAULT_REGION"]topic_id = os.environ["CLS_TOPIC_ID"]auth = base64.b64encode(f"{secret_id}:{secret_key}".encode()).decode()provider = TracerProvider(resource=Resource.create({"service.name": os.environ.get("SERVICE_NAME", "my-llm-app")}))provider.add_span_processor(BatchSpanProcessor(OTLPSpanExporter(endpoint=f"https://{region}.cls.tencentcs.com/v1/traces",headers={"Authorization": f"Basic {auth}","topic_id": topic_id,},),max_export_batch_size=512,schedule_delay_millis=5000,))trace.set_tracer_provider(provider)
instrumentation.py in your business entry.import instrumentationfrom langfuse import observe, propagate_attributes, get_clientfrom langfuse.openai import openai@observe(name="chat", as_type="generation")def chat(user_message: str):with propagate_attributes(user_id="u-123", session_id="s-456", tags=["model:gpt-4o"]):return openai.chat.completions.create(model="gpt-4o",messages=[{"role": "user", "content": user_message}],)if __name__ == "__main__":chat("Hello")get_client().flush()
TracerProvider to control the volume of Trace data reported to CLS.Sampler | Description | Scenario |
ALWAYS_ON | Full sampling | Test environments or low-traffic environments. |
ALWAYS_OFF | No sampling at all | Temporarily disable Trace. |
TraceIdRatioBased(0.1) | Sampling at a 10% ratio | Control write volume in production environments. |
ParentBased(root) | Determine whether to sample based on the parent Span. | Ensures consistent sampling across the entire distributed trace. |
npm install @opentelemetry/sdk-trace-base
import {ParentBasedSampler,TraceIdRatioBasedSampler,} from "@opentelemetry/sdk-trace-base";export const sdk = new NodeSDK({sampler: new ParentBasedSampler({root: new TraceIdRatioBasedSampler(0.1),}),// Keep other configurations unchanged.});
from opentelemetry.sdk.trace.sampling import ParentBased, TraceIdRatioBasedprovider = TracerProvider(sampler=ParentBased(TraceIdRatioBased(0.1)),resource=Resource.create({"service.name": os.environ.get("SERVICE_NAME", "my-llm-app")}))
new OTLPTraceExporter({url: `https://${region}.cls.tencentcs.com/v1/traces`,headers: {Authorization: `Basic ${auth}`,topic_id: topicId,"x-cross-region": "ap-guangzhou", // Source region identifier},})
OTLPSpanExporter(endpoint=f"https://{region}.cls.tencentcs.com/v1/traces",headers={"Authorization": f"Basic {auth}","topic_id": topic_id,"x-cross-region": "ap-guangzhou", # Source region identifier},)
url: `http://${region}.cls.tencentcs.com/v1/traces`,
OTLPSpanExporter(endpoint=f"http://{region}.cls.tencentcs.com/v1/traces",insecure=True, # Test environment only# ...)

* | SELECT traceID, spanID, name, duration, statusCode ORDER BY __TIMESTAMP__ DESC LIMIT 10
traceID:"4bf92f3577b34da6a3ce929d0e0e4736"
attribute and that an index is configured or a JSON extraction function is used:* | SELECT json_extract_scalar(attribute,'$."gen_ai.request.model"') AS model,AVG(duration) AS avg_duration_nsGROUP BY model
resource, scope, and span is reported to CLS according to the OpenTelemetry standard protocol structure.OTel Span Field | CLS LogItem Key | Description |
traceId | traceID | Trace ID, a hex string. |
spanId | spanID | Span ID, a hex string. |
parentSpanId | parentSpanID | Parent Span ID, which is empty for the root Span. |
span.name | name | Span name. |
SpanKind | kind | Span type. |
startTime | start | Span start time, in nanoseconds. |
endTime | end | Span end time, in nanoseconds. |
endTime - startTime | duration | Span duration, in nanoseconds. |
status.code | statusCode | Span status code. |
status.message | statusMessage | Span status message. |
attributes | attribute | Span attributes, a JSON string. |
resource.attributes | resource | Resource attributes, a JSON string. |
events / links | logs / links | Optional. If you need to retain Span Events or Links, serialize them into a JSON string and write it. |
start, end, and duration fields must remain in nanoseconds. Do not divide these fields by 1000 to convert them to microseconds, otherwise the latency will be displayed as one-thousandth of the actual value.flush() or shutdown() to prevent the final batch of Spans from failing to be reported.フィードバック