|
51 | 51 | }, |
52 | 52 | { |
53 | 53 | "cell_type": "code", |
54 | | - "execution_count": 5, |
| 54 | + "execution_count": 11, |
55 | 55 | "id": "edd50a16", |
56 | 56 | "metadata": { |
57 | 57 | "colab": { |
58 | 58 | "base_uri": "https://localhost:8080/" |
59 | 59 | }, |
60 | 60 | "id": "edd50a16", |
61 | | - "outputId": "eaa831da-2621-410a-92c3-25b853ee6ddf" |
| 61 | + "outputId": "68f38db3-48ee-429f-cd6e-2d2ae74e009a" |
62 | 62 | }, |
63 | 63 | "outputs": [ |
64 | 64 | { |
|
73 | 73 | "import os\n", |
74 | 74 | "import requests\n", |
75 | 75 | "import pandas as pd\n", |
76 | | - "from datetime import datetime, timedelta\n", |
| 76 | + "from datetime import datetime, timedelta, time\n", |
77 | 77 | "from typing import Dict, List, Optional, Any\n", |
78 | 78 | "\n", |
79 | 79 | "class AnthropicAdminAPI:\n", |
|
115 | 115 | " try:\n", |
116 | 116 | " client = AnthropicAdminAPI()\n", |
117 | 117 | "\n", |
118 | | - " # Simple test query\n", |
| 118 | + " # Simple test query - snap to start of day to align with bucket boundaries\n", |
119 | 119 | " params = {\n", |
120 | | - " 'starting_at': (datetime.utcnow() - timedelta(days=1)).strftime('%Y-%m-%dT%H:%M:%SZ'),\n", |
121 | | - " 'ending_at': datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ'),\n", |
| 120 | + " 'starting_at': (datetime.combine(datetime.utcnow(), time.min) -\n", |
| 121 | + "timedelta(days=1)).strftime('%Y-%m-%dT%H:%M:%SZ'),\n", |
| 122 | + " 'ending_at': datetime.combine(datetime.utcnow(),\n", |
| 123 | + "time.min).strftime('%Y-%m-%dT%H:%M:%SZ'),\n", |
122 | 124 | " 'bucket_width': '1d',\n", |
123 | 125 | " 'limit': 1\n", |
124 | 126 | " }\n", |
|
158 | 160 | }, |
159 | 161 | { |
160 | 162 | "cell_type": "code", |
161 | | - "execution_count": null, |
| 163 | + "execution_count": 12, |
162 | 164 | "id": "f9b26143", |
163 | 165 | "metadata": { |
164 | 166 | "colab": { |
165 | 167 | "base_uri": "https://localhost:8080/" |
166 | 168 | }, |
167 | 169 | "id": "f9b26143", |
168 | | - "outputId": "00e0f555-c79d-4892-8be4-2cc965259e06" |
| 170 | + "outputId": "c60b91c0-084d-4629-eddd-cf0fb941e042" |
169 | 171 | }, |
170 | 172 | "outputs": [ |
171 | 173 | { |
172 | 174 | "output_type": "stream", |
173 | 175 | "name": "stdout", |
174 | 176 | "text": [ |
175 | 177 | "📊 Usage Summary:\n", |
176 | | - "Uncached input tokens: 3,420\n", |
177 | | - "Output tokens: 43,662\n", |
| 178 | + "Uncached input tokens: 267,751\n", |
| 179 | + "Output tokens: 2,848,746\n", |
178 | 180 | "Cache creation: 0\n", |
179 | 181 | "Cache reads: 0\n", |
180 | 182 | "Cache efficiency: 0.0%\n", |
|
185 | 187 | "source": [ |
186 | 188 | "def get_daily_usage(client, days_back=7):\n", |
187 | 189 | " \"\"\"Get usage data for the last N days.\"\"\"\n", |
188 | | - " end_time = datetime.utcnow()\n", |
| 190 | + " end_time = datetime.combine(datetime.utcnow(), time.min)\n", |
189 | 191 | " start_time = end_time - timedelta(days=days_back)\n", |
190 | 192 | "\n", |
191 | 193 | " params = {\n", |
|
283 | 285 | "source": [ |
284 | 286 | "def get_daily_costs(client, days_back=7):\n", |
285 | 287 | " \"\"\"Get cost data for the last N days.\"\"\"\n", |
286 | | - " end_time = datetime.utcnow()\n", |
| 288 | + " end_time = datetime.combine(datetime.utcnow(), time.min)\n", |
287 | 289 | " start_time = end_time - timedelta(days=days_back)\n", |
288 | 290 | "\n", |
289 | 291 | " params = {\n", |
|
345 | 347 | "base_uri": "https://localhost:8080/" |
346 | 348 | }, |
347 | 349 | "id": "SP4zefdtF0ft", |
348 | | - "outputId": "251a98e6-94a0-48cc-a761-8471c0c946ee" |
| 350 | + "outputId": "a1daa8d0-f36f-474b-9967-6fe00a0efe52" |
349 | 351 | }, |
350 | 352 | "id": "SP4zefdtF0ft", |
351 | | - "execution_count": null, |
| 353 | + "execution_count": 13, |
352 | 354 | "outputs": [ |
353 | 355 | { |
354 | 356 | "output_type": "stream", |
355 | 357 | "name": "stdout", |
356 | 358 | "text": [ |
357 | 359 | "💰 Cost Summary:\n", |
358 | | - "Total cost: $1.4447\n", |
359 | | - "Average daily cost: $0.2408\n" |
| 360 | + "Total cost: $83.7574\n", |
| 361 | + "Average daily cost: $11.9653\n" |
360 | 362 | ] |
361 | 363 | } |
362 | 364 | ] |
363 | 365 | }, |
364 | | - { |
365 | | - "cell_type": "markdown", |
366 | | - "source": [], |
367 | | - "metadata": { |
368 | | - "id": "XQZx3F_vPpw3" |
369 | | - }, |
370 | | - "id": "XQZx3F_vPpw3" |
371 | | - }, |
372 | 366 | { |
373 | 367 | "cell_type": "markdown", |
374 | 368 | "id": "6ce76fc4", |
|
393 | 387 | }, |
394 | 388 | { |
395 | 389 | "cell_type": "code", |
396 | | - "execution_count": 6, |
| 390 | + "execution_count": 14, |
397 | 391 | "id": "87f1a7ac", |
398 | 392 | "metadata": { |
399 | 393 | "colab": { |
400 | 394 | "base_uri": "https://localhost:8080/" |
401 | 395 | }, |
402 | 396 | "id": "87f1a7ac", |
403 | | - "outputId": "c22b2928-e200-4a0e-b3f5-db10cdf12bd7" |
| 397 | + "outputId": "3266318c-8af4-4647-9360-b133ffa82452" |
404 | 398 | }, |
405 | 399 | "outputs": [ |
406 | 400 | { |
|
414 | 408 | " claude-sonnet-4-20250514: 356,766 tokens\n", |
415 | 409 | " claude-opus-4-20250514: 308,223 tokens\n", |
416 | 410 | " claude-opus-4-1-20250805: 199,201 tokens\n", |
417 | | - "Found 6 days of filtered usage data\n" |
| 411 | + "Found 7 days of filtered usage data\n" |
418 | 412 | ] |
419 | 413 | } |
420 | 414 | ], |
421 | 415 | "source": [ |
422 | 416 | "def get_usage_by_model(client, days_back=7):\n", |
423 | 417 | " \"\"\"Get usage data grouped by model, handling pagination automatically.\"\"\"\n", |
424 | | - " end_time = datetime.utcnow()\n", |
| 418 | + " end_time = datetime.combine(datetime.utcnow(), time.min)\n", |
425 | 419 | " start_time = end_time - timedelta(days=days_back)\n", |
426 | 420 | "\n", |
427 | 421 | " params = {\n", |
|
483 | 477 | " print(f\" No usage data found in the last {days_back} days\")\n", |
484 | 478 | " print(\" 💡 Try increasing the time range or check if you have recent API usage\")\n", |
485 | 479 | " else:\n", |
486 | | - " for model, tokens in sorted(model_usage.items(), key=lambda x: x[1], reverse=True):\n", |
| 480 | + " for model, tokens in sorted(model_usage.items(), key=lambda x: x[1],\n", |
| 481 | + "reverse=True):\n", |
487 | 482 | " print(f\" {model}: {tokens:,} tokens\")\n", |
488 | 483 | "\n", |
489 | 484 | " return model_usage\n", |
490 | 485 | "\n", |
491 | 486 | "def filter_usage_example(client):\n", |
492 | 487 | " \"\"\"Example of filtering usage data.\"\"\"\n", |
493 | 488 | " params = {\n", |
494 | | - " 'starting_at': (datetime.utcnow() - timedelta(days=7)).strftime('%Y-%m-%dT%H:%M:%SZ'),\n", |
495 | | - " 'ending_at': datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ'),\n", |
| 489 | + " 'starting_at': (datetime.combine(datetime.utcnow(), time.min) -\n", |
| 490 | + "timedelta(days=7)).strftime('%Y-%m-%dT%H:%M:%SZ'),\n", |
| 491 | + " 'ending_at': datetime.combine(datetime.utcnow(),\n", |
| 492 | + "time.min).strftime('%Y-%m-%dT%H:%M:%SZ'),\n", |
496 | 493 | " 'models[]': ['claude-3-5-sonnet-20241022'], # Filter to specific model\n", |
497 | 494 | " 'service_tiers[]': ['standard'], # Filter to standard tier\n", |
498 | 495 | " 'bucket_width': '1d'\n", |
|
520 | 517 | }, |
521 | 518 | { |
522 | 519 | "cell_type": "code", |
523 | | - "execution_count": null, |
| 520 | + "execution_count": 18, |
524 | 521 | "id": "d7cc5437", |
525 | 522 | "metadata": { |
526 | 523 | "colab": { |
527 | 524 | "base_uri": "https://localhost:8080/" |
528 | 525 | }, |
529 | 526 | "id": "d7cc5437", |
530 | | - "outputId": "b2b1a80a-e13c-427d-ed9f-ccaa3e478eee" |
| 527 | + "outputId": "e7875fb4-09ae-44d2-f5fc-12a4cbdcce5a" |
531 | 528 | }, |
532 | 529 | "outputs": [ |
533 | 530 | { |
|
538 | 535 | " Page 1: 24 time buckets\n", |
539 | 536 | " Page 2: 24 time buckets\n", |
540 | 537 | " Page 3: 24 time buckets\n", |
541 | | - " Page 4: 24 time buckets\n", |
542 | | - " Page 5: 24 time buckets\n", |
543 | | - "📊 Total retrieved: 120 time buckets\n", |
544 | | - "📈 Total tokens across all data: 0\n" |
| 538 | + "✅ Complete: Retrieved all data in 3 pages\n", |
| 539 | + "📊 Total retrieved: 72 time buckets\n", |
| 540 | + "📈 Total tokens across all data: 1,336,287\n" |
545 | 541 | ] |
546 | 542 | } |
547 | 543 | ], |
|
586 | 582 | " print(f\"📊 Total retrieved: {len(all_data)} time buckets\")\n", |
587 | 583 | " return all_data\n", |
588 | 584 | "\n", |
589 | | - "def large_dataset_example(client, days_back=30):\n", |
| 585 | + "def large_dataset_example(client, days_back=3):\n", |
590 | 586 | " \"\"\"Example of handling a large dataset with pagination.\"\"\"\n", |
| 587 | + " # Use recent time range to ensure we have data\n", |
| 588 | + " start_time = datetime.combine(datetime.utcnow(), time.min) - timedelta(days=days_back)\n", |
| 589 | + " end_time = datetime.combine(datetime.utcnow(), time.min)\n", |
| 590 | + "\n", |
591 | 591 | " params = {\n", |
592 | | - " 'starting_at': (datetime.utcnow() - timedelta(days=days_back)).strftime('%Y-%m-%dT%H:%M:%SZ'),\n", |
593 | | - " 'ending_at': datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ'),\n", |
| 592 | + " 'starting_at': start_time.strftime('%Y-%m-%dT%H:%M:%SZ'),\n", |
| 593 | + " 'ending_at': end_time.strftime('%Y-%m-%dT%H:%M:%SZ'),\n", |
594 | 594 | " 'bucket_width': '1h', # Hourly data for more buckets\n", |
595 | 595 | " 'group_by[]': ['model'],\n", |
596 | 596 | " 'limit': 24 # One day per page\n", |
|
609 | 609 | "\n", |
610 | 610 | " return all_buckets\n", |
611 | 611 | "\n", |
612 | | - "# Example usage\n", |
| 612 | + "# Example usage - use shorter time range to find recent data\n", |
613 | 613 | "if client:\n", |
614 | | - " large_dataset = large_dataset_example(client, days_back=14)" |
| 614 | + " large_dataset = large_dataset_example(client, days_back=3)" |
615 | 615 | ] |
616 | 616 | }, |
617 | 617 | { |
|
628 | 628 | }, |
629 | 629 | { |
630 | 630 | "cell_type": "code", |
631 | | - "execution_count": null, |
| 631 | + "execution_count": 16, |
632 | 632 | "id": "f365296a", |
633 | 633 | "metadata": { |
634 | 634 | "colab": { |
635 | 635 | "base_uri": "https://localhost:8080/" |
636 | 636 | }, |
637 | 637 | "id": "f365296a", |
638 | | - "outputId": "42120afa-d6a9-4789-fcfd-aaa1e9f19032" |
| 638 | + "outputId": "87b4a733-6f90-4b8d-a109-7a23281b2a4d" |
639 | 639 | }, |
640 | 640 | "outputs": [ |
641 | 641 | { |
642 | 642 | "output_type": "stream", |
643 | 643 | "name": "stdout", |
644 | 644 | "text": [ |
645 | | - "✅ Exported 6 rows to my_usage_data.csv\n", |
646 | | - "✅ Exported 12 cost records to my_cost_data.csv\n" |
| 645 | + "✅ Exported 36 rows to my_usage_data.csv\n", |
| 646 | + "✅ Exported 72 cost records to my_cost_data.csv\n" |
647 | 647 | ] |
648 | 648 | } |
649 | 649 | ], |
|
654 | 654 | "def export_usage_to_csv(client, output_file=\"usage_data.csv\", days_back=30):\n", |
655 | 655 | " \"\"\"Export usage data to CSV for external analysis.\"\"\"\n", |
656 | 656 | "\n", |
| 657 | + " end_time = datetime.combine(datetime.utcnow(), time.min)\n", |
| 658 | + " start_time = end_time - timedelta(days=days_back)\n", |
| 659 | + "\n", |
657 | 660 | " params = {\n", |
658 | | - " 'starting_at': (datetime.utcnow() - timedelta(days=days_back)).strftime('%Y-%m-%dT%H:%M:%SZ'),\n", |
659 | | - " 'ending_at': datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ'),\n", |
| 661 | + " 'starting_at': start_time.strftime('%Y-%m-%dT%H:%M:%SZ'),\n", |
| 662 | + " 'ending_at': end_time.strftime('%Y-%m-%dT%H:%M:%SZ'),\n", |
660 | 663 | " 'group_by[]': ['model', 'service_tier', 'workspace_id'],\n", |
661 | 664 | " 'bucket_width': '1d'\n", |
662 | 665 | " }\n", |
|
721 | 724 | "def export_costs_to_csv(client, output_file=\"cost_data.csv\", days_back=30):\n", |
722 | 725 | " \"\"\"Export cost data to CSV.\"\"\"\n", |
723 | 726 | "\n", |
| 727 | + " end_time = datetime.combine(datetime.utcnow(), time.min)\n", |
| 728 | + " start_time = end_time - timedelta(days=days_back)\n", |
| 729 | + "\n", |
724 | 730 | " params = {\n", |
725 | | - " 'starting_at': (datetime.utcnow() - timedelta(days=days_back)).strftime('%Y-%m-%dT%H:%M:%SZ'),\n", |
726 | | - " 'ending_at': datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ'),\n", |
| 731 | + " 'starting_at': start_time.strftime('%Y-%m-%dT%H:%M:%SZ'),\n", |
| 732 | + " 'ending_at': end_time.strftime('%Y-%m-%dT%H:%M:%SZ'),\n", |
727 | 733 | " 'group_by[]': ['workspace_id', 'description']\n", |
728 | 734 | " }\n", |
729 | 735 | "\n", |
|
0 commit comments