Metadata-Version: 2.4
Name: pysttl
Version: 0.1.1
Summary: Periodic stack-trace sampler for Python performance profiling.
Project-URL: Homepage, https://gitlab.tokyo.optim.co.jp/naganuma-test/python-stacktrace-logger
Project-URL: Repository, https://gitlab.tokyo.optim.co.jp/naganuma-test/python-stacktrace-logger
Project-URL: Issues, https://gitlab.tokyo.optim.co.jp/naganuma-test/python-stacktrace-logger/-/issues
Author-email: Shunsuke Naganuma <naganuma@optim.co.jp>
License: MIT
Keywords: debugging,performance,profiling,sampler,stack-trace
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: POSIX
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Debuggers
Classifier: Topic :: System :: Monitoring
Requires-Python: >=3.11
Provides-Extra: dev
Requires-Dist: build>=1.2; extra == 'dev'
Requires-Dist: twine>=6.2; extra == 'dev'
Description-Content-Type: text/markdown

# pysttl

`pysttl` (Python Sampling Thread Trace Logger) は、Python アプリケーションのパフォーマンスのボトルネックを特定するためのスタックトレース定期サンプラーです。`SIGALRM` を利用して指定間隔ごとに**全スレッド**のスタックトレースを取得し、JSON Lines 形式でログファイルに追記します。

得られたログを解析することで、どの関数・どの行で時間を費やしているかを統計的に把握できます (poor-man's profiler の発想)。

## 動作要件

- Python 3.11 以上
- POSIX 系 OS (Linux / macOS) — 内部で `signal.SIGALRM` を使用するため、Windows では動作しません。
- `start()` はメインスレッドからのみ呼び出せます (`signal.signal()` の制約)。
- `signal.SIGALRM` / `signal.setitimer(ITIMER_REAL, ...)` を内部で利用するため、同じシグナル/タイマーを使う他のコードとは併用できません。

## インストール

```bash
pip install pysttl
```

ローカルチェックアウトから直接インストールする場合:

```bash
pip install .
```

開発用の追加依存 (ビルド/PyPI アップロード用) も入れる場合:

```bash
pip install -e '.[dev]'
```

## 使い方

### 1. コンテキストマネージャ (推奨)

```python
import pysttl

with pysttl.trace():
    do_heavy_work()
```

ブロックを抜けると自動的に `stop()` が呼ばれ、SIGALRM ハンドラと `setitimer` の状態は呼び出し前に復元されます。

### 2. 関数 API

```python
import pysttl

pysttl.start(log_file_path="/tmp/backtrace.log", interval=1.0)
try:
    do_heavy_work()
finally:
    pysttl.stop()
```

### 3. デフォルト値の上書き

`log_file_path` と `interval` のデフォルト値はモジュール属性として公開されており、外部から上書き可能です。`start()` / `trace()` は呼び出し時にその時点の値を参照します。

```python
import pysttl

pysttl.DEFAULT_LOG_FILE_PATH = "/var/log/myapp/backtrace.log"
pysttl.DEFAULT_INTERVAL = 0.5  # 500ms 間隔でサンプル

pysttl.start()  # 上記の上書き値が適用される
```

引数を明示的に渡した場合はそちらが優先されます。

## 出力フォーマット

ログは **JSON Lines** で書き出されます。1 行 = 1 サンプル = その時点の全スレッドのスタックトレースです。

```json
{
  "threads": [
    {
      "backtrace": [
        "<FrameSummary file '/path/to/main.py', line 14 in main>",
        "<FrameSummary file '/path/to/core.py', line 80 in busy_loop>"
      ],
      "datetime": "2026-05-08T21:00:00.123456",
      "thread_name": "MainThread",
      "thread_ident": 140123456789
    }
  ]
}
```

`backtrace` は呼び出し元 → 呼び出し先の順 (root -> leaf) に並んでいます。

## API リファレンス

| シンボル | 種別 | 説明 |
| --- | --- | --- |
| `pysttl.start(log_file_path=None, interval=None)` | 関数 | サンプリング開始。`None` の場合は対応する `DEFAULT_*` を参照。 |
| `pysttl.stop()` | 関数 | サンプリング停止 + SIGALRM ハンドラ復元。未起動なら no-op。 |
| `pysttl.trace(log_file_path=None, interval=None)` | コンテキストマネージャ | `start()` / `stop()` のラッパー。 |
| `pysttl.DEFAULT_LOG_FILE_PATH` | 定数 (str) | 既定の出力先。初期値 `"/tmp/backtrace.log"`。 |
| `pysttl.DEFAULT_INTERVAL` | 定数 (float) | 既定のサンプリング間隔 [秒]。初期値 `1.0`。 |

## 制限事項

- `signal.SIGALRM` を `pysttl` が占有するため、`signal.alarm()` や `setitimer(ITIMER_REAL, ...)` を別途使用するコードと併用できません。
- シグナルハンドラ内でファイル I/O (JSON シリアライズ + 追記書き込み) を行うため、I/O が遅い環境では実際の処理スレッドを意図せずブロックする可能性があります。本番常用ではなく調査用途を想定しています。
- `start()` 中の二重起動はエラーになります。設定変更時はいったん `stop()` してから再 `start()` してください。

## ビルドと公開

```bash
# ビルド (sdist + wheel を dist/ に生成)
python -m build

# 動作確認用に別 venv へインストール
pip install dist/pysttl-*.whl

# PyPI へアップロード (要 ~/.pypirc)
twine upload dist/*
```

`uv` ユーザーは `uv build` / `uv publish` も利用可能です。

## ライセンス

MIT License。詳細は `pyproject.toml` を参照してください。
