Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

# axiom-py [![CI][ci_badge]][ci] [![PyPI version][pypi_badge]][pypi] [![Python version][version_badge]][pypi]

## Synchronous Client

```py
import axiom_py

Expand All @@ -12,6 +14,49 @@ client.ingest_events(dataset="DATASET_NAME", events=[{"foo": "bar"}, {"bar": "ba
client.query(r"['DATASET_NAME'] | where foo == 'bar' | limit 100")
```

## Asynchronous Client

The library also provides an async client for use with asyncio:

```py
import asyncio
from axiom_py import AsyncClient

async def main():
async with AsyncClient() as client:
# Ingest events
await client.ingest_events(
dataset="DATASET_NAME",
events=[{"foo": "bar"}, {"bar": "baz"}]
)

# Query data
result = await client.query(r"['DATASET_NAME'] | where foo == 'bar' | limit 100")
print(f"Found {len(result.matches)} matches")

asyncio.run(main())
```

### Concurrent Operations

The async client enables efficient concurrent operations:

```py
import asyncio
from axiom_py import AsyncClient

async def main():
async with AsyncClient() as client:
# Ingest to multiple datasets concurrently
await asyncio.gather(
client.ingest_events("dataset1", [{"event": "data1"}]),
client.ingest_events("dataset2", [{"event": "data2"}]),
client.ingest_events("dataset3", [{"event": "data3"}]),
)

asyncio.run(main())
```

## Install

```sh
Expand Down
46 changes: 46 additions & 0 deletions examples/async_basic.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
"""
Basic async example for axiom-py.

This example demonstrates basic usage of the async Axiom client for
ingesting events and querying data.
"""

import asyncio
import os
from axiom_py import AsyncClient


async def main():
"""Main async function demonstrating basic usage."""
# Initialize client with token from environment
# You can also pass token explicitly: AsyncClient(token="your-token")
async with AsyncClient() as client:
dataset_name = os.getenv("AXIOM_DATASET", "my-dataset")

# Ingest some sample events
print("Ingesting events...")
events = [
{"user": "alice", "action": "login", "status": "success"},
{"user": "bob", "action": "purchase", "amount": 99.99},
{"user": "charlie", "action": "logout", "status": "success"},
]

result = await client.ingest_events(dataset_name, events)
print(
f"Ingested {result.ingested} events ({result.processed_bytes} bytes)"
)

# Query the data
print("\nQuerying data...")
query_result = await client.query(
f"['{dataset_name}'] | where action == 'login' | limit 10"
)
print(f"Found {len(query_result.matches)} matches")

# Print the matches
for match in query_result.matches:
print(f" - {match}")


if __name__ == "__main__":
asyncio.run(main())
72 changes: 72 additions & 0 deletions examples/async_concurrent.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
"""
Concurrent operations example for axiom-py async client.

This example demonstrates how to use asyncio.gather() to perform
multiple operations concurrently for better performance.
"""

import asyncio
import time
from axiom_py import AsyncClient


async def ingest_to_dataset(client: AsyncClient, dataset: str, count: int):
"""Ingest events to a specific dataset."""
events = [{"index": i, "dataset": dataset} for i in range(count)]
result = await client.ingest_events(dataset, events)
print(f"Ingested {result.ingested} events to {dataset}")
return result


async def query_dataset(client: AsyncClient, dataset: str):
"""Query a specific dataset."""
result = await client.query(f"['{dataset}'] | limit 10")
print(f"Queried {dataset}: found {len(result.matches)} matches")
return result


async def main():
"""Main async function demonstrating concurrent operations."""
async with AsyncClient() as client:
print("=== Concurrent Ingestion Example ===")
start_time = time.time()

# Ingest to multiple datasets concurrently
datasets = ["dataset1", "dataset2", "dataset3"]
await asyncio.gather(
*[ingest_to_dataset(client, dataset, 100) for dataset in datasets]
)

elapsed = time.time() - start_time
print(f"Completed concurrent ingestion in {elapsed:.2f} seconds\n")

print("=== Concurrent Query Example ===")
start_time = time.time()

# Query multiple datasets concurrently
await asyncio.gather(
*[query_dataset(client, dataset) for dataset in datasets]
)

elapsed = time.time() - start_time
print(f"Completed concurrent queries in {elapsed:.2f} seconds\n")

print("=== Mixed Operations Example ===")
start_time = time.time()

# Mix ingestion and queries concurrently
await asyncio.gather(
ingest_to_dataset(client, "dataset1", 50),
query_dataset(client, "dataset2"),
ingest_to_dataset(client, "dataset3", 50),
query_dataset(client, "dataset1"),
)

elapsed = time.time() - start_time
print(
f"Completed mixed concurrent operations in {elapsed:.2f} seconds"
)


if __name__ == "__main__":
asyncio.run(main())
61 changes: 61 additions & 0 deletions examples/async_datasets.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
"""
Async dataset management example for axiom-py.

This example demonstrates how to use the async client to manage
datasets: create, list, update, and delete.
"""

import asyncio
from datetime import timedelta
from axiom_py import AsyncClient


async def main():
"""Main async function demonstrating dataset management."""
async with AsyncClient() as client:
dataset_name = "example-dataset-async"

# Create a new dataset
print(f"Creating dataset: {dataset_name}")
dataset = await client.datasets.create(
dataset_name, "Example dataset for async operations"
)
print(f"Created: {dataset.name} - {dataset.description}")

# List all datasets
print("\nListing all datasets:")
datasets = await client.datasets.get_list()
for ds in datasets:
print(f" - {ds.name}: {ds.description}")

# Get specific dataset
print(f"\nGetting dataset: {dataset_name}")
dataset = await client.datasets.get(dataset_name)
print(f"Found: {dataset.name}")

# Update dataset description
print(f"\nUpdating dataset: {dataset_name}")
dataset = await client.datasets.update(
dataset_name, "Updated description for async example"
)
print(f"Updated: {dataset.name} - {dataset.description}")

# Ingest some sample data
print(f"\nIngesting data to {dataset_name}")
events = [{"message": f"Event {i}", "value": i} for i in range(10)]
result = await client.ingest_events(dataset_name, events)
print(f"Ingested {result.ingested} events")

# Trim dataset (remove data older than 7 days)
print(f"\nTrimming dataset: {dataset_name}")
await client.datasets.trim(dataset_name, timedelta(days=7))
print("Trim operation completed")

# Delete the dataset
print(f"\nDeleting dataset: {dataset_name}")
await client.datasets.delete(dataset_name)
print("Dataset deleted")


if __name__ == "__main__":
asyncio.run(main())
51 changes: 51 additions & 0 deletions examples/async_logging.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
"""
Async logging example for axiom-py.

This example demonstrates how to use AsyncAxiomHandler to send
Python logs to Axiom asynchronously.
"""

import asyncio
import logging
from axiom_py import AsyncClient, AsyncAxiomHandler


async def main():
"""Main async function demonstrating async logging."""
# Initialize the async client
async with AsyncClient() as client:
# Create and configure the async handler
handler = AsyncAxiomHandler(
client=client,
dataset="logs",
interval=1, # Flush every second
)

# Configure the root logger
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
logger.addHandler(handler)

# Log some messages
logger.info("Application started")
logger.debug("Debug message with details", extra={"user_id": 123})
logger.warning("This is a warning")
logger.error("An error occurred", extra={"error_code": "E001"})

# Simulate some async work
await asyncio.sleep(0.5)

logger.info("Processing data...")
for i in range(5):
logger.info(f"Processing item {i}", extra={"item_id": i})
await asyncio.sleep(0.1)

logger.info("Application finished")

# Important: Close the handler to flush remaining logs
await handler.close()
print("Logs sent to Axiom")


if __name__ == "__main__":
asyncio.run(main())
Loading
Loading