Skip to main content

pstone — Profit Stone Telemetry SDK

고객 AI 앱에 설치하는 in-process 관측 SDK입니다.
OpenTelemetry로 LLM·도구 호출을 수집해 Profit Stone SaaS Ingest API로 보내고, Backend가 Workspace API Key로 workspace_id를 붙여 ClickHouse에 저장합니다.

Sentry를 붙이듯, 앱에 패키지를 설치하고 init에 API Key만 넣으면 됩니다.

from pstone import pstone

pstone.init("psk_live_...")

상태: 0.1.0 Alpha — Python MVP. JS(@pstone/sdk)는 후속.

설계 문서: docs/sdk-design.md


목차

  1. 설치
  2. 빠른 시작
  3. API Key
  4. 환경 변수
  5. OpenAI / Anthropic 계측
  6. 옵션
  7. 수동 Span
  8. flush / shutdown
  9. 데이터 흐름
  10. 로컬 개발
  11. PyPI 배포

설치

일반 (배포 후)

pip install pstone

OpenAI / Anthropic 계측을 쓰려면 해당 SDK도 앱에 설치되어 있어야 합니다.

pip install pstone openai anthropic
# 또는 extras (패키지 배포 설정에 따름)
pip install "pstone[openai,anthropic]"

개발 (이 레포)

cd profitstone_sdk
uv sync
uv run pytest

빠른 시작

  1. Profit Stone Dashboard에서 Workspace API Key를 발급합니다.
  2. 앱 시작 시점에 pstone.init한 번 호출합니다 (Sentry init과 동일).
  3. 기존 OpenAI / Anthropic 호출 코드는 그대로 둡니다. init이 설치된 라이브러리를 자동 계측합니다.
import os
from openai import OpenAI
from pstone import pstone

# 1) SDK 초기화 (앱 부팅 시 1회)
pstone.init(os.environ["PSTONE_API_KEY"])

# 2) 평소처럼 AI 호출 — Span이 자동 수집되어 Ingest로 전송됨
client = OpenAI()
resp = client.chat.completions.create(
    model="gpt-4o-mini",
    messages=[{"role": "user", "content": "Hello"}],
)
print(resp.choices[0].message.content)

# 3) 프로세스 종료 전 (선택) 미전송 Span flush
pstone.flush()

Anthropic도 동일합니다.

from anthropic import Anthropic
from pstone import pstone

pstone.init("psk_live_...")

client = Anthropic()
msg = client.messages.create(
    model="claude-sonnet-4-5",
    max_tokens=256,
    messages=[{"role": "user", "content": "Hello"}],
)

API Key

항목 설명
발급 위치 Dashboard → Workspace → API Keys
스코프 Workspace 단위 (backend-design.md)
전달 pstone.init("psk_...") 또는 환경 변수 PSTONE_API_KEY
서버 처리 Backend가 키를 검증하고 workspace_id를 찾아 ClickHouse에 함께 저장

SDK는 workspace_id를 직접 보내지 않습니다. 키만 보내면 됩니다.

from pstone import pstone

# 인자로 전달
pstone.init("psk_live_xxxxxxxx")

# 또는 환경 변수만 설정한 뒤
# export PSTONE_API_KEY=psk_live_xxxxxxxx
pstone.init()

키를 소스코드·로그·이슈에 커밋하지 마세요.


환경 변수

변수 필수 설명
PSTONE_API_KEY 권장 Workspace API Key (init 인자 생략 시 사용)
PSTONE_INGEST_URL 선택 Ingest 베이스 URL (기본 https://api.profitstone.ai)
PSTONE_SERVICE_NAME 선택 OTel service.name (기본 pstone-app)

실제 전송 경로는 {PSTONE_INGEST_URL}/v1/ingest/traces 입니다.

로컬 Backend에 붙일 때:

export PSTONE_API_KEY=psk_test_...
export PSTONE_INGEST_URL=http://localhost:8000
pstone.init(ingest_url="http://localhost:8000")

OpenAI / Anthropic 계측

자동 (권장)

pstone.init(..., instrument=True) (기본값)이면, 프로세스에 openai / anthropic 패키지가 설치되어 있을 때 chat / messages API를 패치합니다.

  • OpenAI: chat.completions.create (및 parse가 있으면 함께)
  • Anthropic: messages.create
  • OpenAI-compatible (예: Perplexity 등 OpenAI 클라이언트 + 커스텀 base_url): OpenAI 계측 경로를 그대로 탑니다.

명시적 wrap

글로벌 패치 대신 클라이언트만 감쌀 수 있습니다.

from openai import OpenAI
from anthropic import Anthropic
from pstone import pstone

pstone.init("psk_live_...", instrument=False)

openai_client = pstone.wrap_openai(OpenAI())
anthropic_client = pstone.wrap_anthropic(Anthropic())

수집되는 주요 속성

OpenTelemetry gen_ai.* 계열:

Attribute
gen_ai.system openai, anthropic
gen_ai.request.model gpt-4o-mini
gen_ai.prompt 메시지 직렬화 (redaction 적용 가능)
gen_ai.completion 응답 텍스트
gen_ai.usage.input_tokens 입력 토큰
gen_ai.usage.output_tokens 출력 토큰

계측 코드는 원본 API 예외를 바꾸지 않습니다. Span 기록 실패는 조용히 무시되어 앱 핫 패스를 보호합니다.


옵션

pstone.init(
    "psk_live_...",
    ingest_url="https://api.profitstone.ai",
    service_name="my-ai-app",
    capture_content=True,   # 프롬프트·completion 수집
    redact=True,            # 이메일·전화번호 등 기본 PII 마스킹
    instrument=True,        # 자동 패치 on/off
    instrument_openai=True,
    instrument_anthropic=True,
)
옵션 기본 설명
capture_content True 프롬프트/completion을 Span에 넣을지
redact True 기본 PII 마스킹
instrument True 자동 계측 전체 on/off
instrument_openai True OpenAI 패치
instrument_anthropic True Anthropic 패치
use_batch True BatchSpanProcessor (테스트에선 False 권장)

민감 프롬프트를 보내지 않으려면:

pstone.init("psk_live_...", capture_content=False)

수동 Span

자동 계측 밖(커스텀 HTTP 등)에서는 헬퍼를 직접 쓸 수 있습니다.

from pstone.span import start_llm_span, record_llm_response

with start_llm_span(
    name="custom.llm",
    system="perplexity",
    model="sonar",
    prompt=[{"role": "user", "content": "hi"}],
) as span:
    # ... 호출 ...
    record_llm_response(
        span,
        completion="...",
        input_tokens=10,
        output_tokens=20,
    )

flush / shutdown

메서드 용도
pstone.flush() 대기 중인 Span을 Ingest로 강제 전송
pstone.shutdown() flush + 계측 해제 + TracerProvider 종료

배치 전송이므로, 짧은 CLI/스크립트는 종료 전에 flush()를 호출하세요.

try:
    # ...
finally:
    pstone.flush()
    pstone.shutdown()

데이터 흐름

고객 앱
  pstone.init(API Key)
  → OpenTelemetry Tracer + OTLP/HTTP Exporter
  → AI API 호출 시 Span 기록
  → POST {INGEST_URL}/v1/ingest/traces
       Authorization: Bearer <API Key>

profitstone_backend
  → API Key 검증 → workspace_id 해석
  → ClickHouse에 span + workspace_id 저장

SDK는 DB에 직접 붙지 않습니다. HTTPS Ingest만 사용합니다.


로컬 개발

cd profitstone_sdk
uv sync
uv run pytest
uv build

테스트는 InMemorySpanExporter로 Ingest 없이 Span 속성만 검증합니다.

관련 문서:

문서 경로
SDK 설계 docs/sdk-design.md
아키텍처 ../profitstone_docs/개발문서/architecture.md
Backend ../profitstone_backend/docs/backend-design.md
에이전트 맵 AGENTS.md

PyPI 배포

pip install pstone이 되려면 PyPI에 업로드해야 합니다.

# 1) 토큰 설정 (최초 1회)
cp .env.example .env
# .env 에 UV_PUBLISH_TOKEN=pypi-... 입력

# 2) 배포
make publish

# 또는 직접
uv build
uv publish   # UV_PUBLISH_TOKEN 또는 Trusted Publisher

성공 직후부터 사용자가 pip install pstone을 사용할 수 있습니다.
절차 상세: docs/sdk-design.md §13.


라이선스

MIT

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pstone-0.1.1.tar.gz (122.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pstone-0.1.1-py3-none-any.whl (17.4 kB view details)

Uploaded Python 3

File details

Details for the file pstone-0.1.1.tar.gz.

File metadata

  • Download URL: pstone-0.1.1.tar.gz
  • Upload date:
  • Size: 122.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.27 {"installer":{"name":"uv","version":"0.11.27","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for pstone-0.1.1.tar.gz
Algorithm Hash digest
SHA256 fb1481b8b4dbd4e9f9c14fa2f6bec43c265b6cd945a0cd623354c1cc5bc06589
MD5 8df62a6314e4a5fbde421fe9fe5ab258
BLAKE2b-256 cc36465f1e876783b6536202ba360fea428143432ee536418d5ce347bd5d0101

See more details on using hashes here.

File details

Details for the file pstone-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: pstone-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 17.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.27 {"installer":{"name":"uv","version":"0.11.27","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for pstone-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 09e8154b3c25a03da9da97fc641131e7ed42baf8129073c541f072a97acbef55
MD5 fd76ad50da372932b3d635afc5217ed0
BLAKE2b-256 1009b766a1d6b9b26d087c0c2bffef4eb362c948e4559a97cc4e751c0a3d0e51

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page