honeycomb-api 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (453) hide show
  1. honeycomb/__init__.py +217 -0
  2. honeycomb/_generated/__init__.py +8 -0
  3. honeycomb/_generated/api/__init__.py +1 -0
  4. honeycomb/_generated/api/auth/__init__.py +0 -0
  5. honeycomb/_generated/api/auth/get_auth.py +172 -0
  6. honeycomb/_generated/api/auth/get_v2_auth.py +168 -0
  7. honeycomb/_generated/api/boards/__init__.py +0 -0
  8. honeycomb/_generated/api/boards/create_board.py +217 -0
  9. honeycomb/_generated/api/boards/create_board_view.py +237 -0
  10. honeycomb/_generated/api/boards/delete_board.py +191 -0
  11. honeycomb/_generated/api/boards/delete_board_view.py +210 -0
  12. honeycomb/_generated/api/boards/get_board.py +208 -0
  13. honeycomb/_generated/api/boards/get_board_view.py +214 -0
  14. honeycomb/_generated/api/boards/list_board_views.py +206 -0
  15. honeycomb/_generated/api/boards/list_boards.py +177 -0
  16. honeycomb/_generated/api/boards/update_board.py +238 -0
  17. honeycomb/_generated/api/boards/update_board_view.py +250 -0
  18. honeycomb/_generated/api/burn_alerts/__init__.py +0 -0
  19. honeycomb/_generated/api/burn_alerts/create_burn_alert.py +224 -0
  20. honeycomb/_generated/api/burn_alerts/delete_burn_alert.py +204 -0
  21. honeycomb/_generated/api/burn_alerts/get_burn_alert.py +208 -0
  22. honeycomb/_generated/api/burn_alerts/list_burn_alerts_by_slo.py +220 -0
  23. honeycomb/_generated/api/calculated_fields/__init__.py +0 -0
  24. honeycomb/_generated/api/calculated_fields/create_calculated_field.py +239 -0
  25. honeycomb/_generated/api/calculated_fields/delete_calculated_field.py +225 -0
  26. honeycomb/_generated/api/calculated_fields/get_calculated_field.py +207 -0
  27. honeycomb/_generated/api/calculated_fields/list_calculated_fields.py +252 -0
  28. honeycomb/_generated/api/calculated_fields/update_calculated_field.py +242 -0
  29. honeycomb/_generated/api/columns/__init__.py +0 -0
  30. honeycomb/_generated/api/columns/create_column.py +241 -0
  31. honeycomb/_generated/api/columns/delete_column.py +221 -0
  32. honeycomb/_generated/api/columns/get_column.py +206 -0
  33. honeycomb/_generated/api/columns/list_columns.py +256 -0
  34. honeycomb/_generated/api/columns/update_column.py +242 -0
  35. honeycomb/_generated/api/dataset_definitions/__init__.py +0 -0
  36. honeycomb/_generated/api/dataset_definitions/list_dataset_definitions.py +193 -0
  37. honeycomb/_generated/api/dataset_definitions/patch_dataset_definitions.py +235 -0
  38. honeycomb/_generated/api/datasets/__init__.py +0 -0
  39. honeycomb/_generated/api/datasets/create_dataset.py +227 -0
  40. honeycomb/_generated/api/datasets/delete_dataset.py +251 -0
  41. honeycomb/_generated/api/datasets/get_dataset.py +195 -0
  42. honeycomb/_generated/api/datasets/list_datasets.py +177 -0
  43. honeycomb/_generated/api/datasets/update_dataset.py +217 -0
  44. honeycomb/_generated/api/enhance/__init__.py +0 -0
  45. honeycomb/_generated/api/enhance/record_enhance_indexer_usage.py +231 -0
  46. honeycomb/_generated/api/environments/__init__.py +0 -0
  47. honeycomb/_generated/api/environments/create_environment.py +247 -0
  48. honeycomb/_generated/api/environments/delete_environment.py +245 -0
  49. honeycomb/_generated/api/environments/get_environment.py +213 -0
  50. honeycomb/_generated/api/environments/list_environments.py +245 -0
  51. honeycomb/_generated/api/environments/update_environment.py +254 -0
  52. honeycomb/_generated/api/events/__init__.py +0 -0
  53. honeycomb/_generated/api/events/create_event.py +269 -0
  54. honeycomb/_generated/api/events/create_events.py +314 -0
  55. honeycomb/_generated/api/key_management/__init__.py +0 -0
  56. honeycomb/_generated/api/key_management/create_api_key.py +286 -0
  57. honeycomb/_generated/api/key_management/delete_api_key.py +223 -0
  58. honeycomb/_generated/api/key_management/get_api_key.py +225 -0
  59. honeycomb/_generated/api/key_management/list_api_keys.py +281 -0
  60. honeycomb/_generated/api/key_management/update_api_key.py +270 -0
  61. honeycomb/_generated/api/kinesis_events/__init__.py +0 -0
  62. honeycomb/_generated/api/kinesis_events/create_kinesis_events.py +220 -0
  63. honeycomb/_generated/api/marker_settings/__init__.py +0 -0
  64. honeycomb/_generated/api/marker_settings/create_marker_setting.py +209 -0
  65. honeycomb/_generated/api/marker_settings/delete_marker_settings.py +194 -0
  66. honeycomb/_generated/api/marker_settings/list_marker_settings.py +186 -0
  67. honeycomb/_generated/api/marker_settings/update_marker_settings.py +230 -0
  68. honeycomb/_generated/api/markers/__init__.py +0 -0
  69. honeycomb/_generated/api/markers/create_marker.py +220 -0
  70. honeycomb/_generated/api/markers/create_marker_v2.py +253 -0
  71. honeycomb/_generated/api/markers/delete_marker.py +200 -0
  72. honeycomb/_generated/api/markers/get_marker.py +194 -0
  73. honeycomb/_generated/api/markers/update_marker.py +233 -0
  74. honeycomb/_generated/api/markers/update_marker_v2.py +262 -0
  75. honeycomb/_generated/api/pipelines/__init__.py +0 -0
  76. honeycomb/_generated/api/pipelines/get_pipeline_configuration.py +306 -0
  77. honeycomb/_generated/api/pipelines/record_pipeline_usage.py +244 -0
  78. honeycomb/_generated/api/pipelines/update_pipeline_configuration_rollout.py +261 -0
  79. honeycomb/_generated/api/queries/__init__.py +0 -0
  80. honeycomb/_generated/api/queries/create_query.py +224 -0
  81. honeycomb/_generated/api/queries/get_query.py +208 -0
  82. honeycomb/_generated/api/query_annotations/__init__.py +0 -0
  83. honeycomb/_generated/api/query_annotations/create_query_annotation.py +226 -0
  84. honeycomb/_generated/api/query_annotations/delete_query_annotation.py +198 -0
  85. honeycomb/_generated/api/query_annotations/get_query_annotation.py +202 -0
  86. honeycomb/_generated/api/query_annotations/list_query_annotations.py +217 -0
  87. honeycomb/_generated/api/query_annotations/update_query_annotation.py +237 -0
  88. honeycomb/_generated/api/query_data/__init__.py +0 -0
  89. honeycomb/_generated/api/query_data/create_query_result.py +247 -0
  90. honeycomb/_generated/api/query_data/get_query_result.py +208 -0
  91. honeycomb/_generated/api/recipients/__init__.py +0 -0
  92. honeycomb/_generated/api/recipients/create_recipient.py +317 -0
  93. honeycomb/_generated/api/recipients/delete_recipient.py +199 -0
  94. honeycomb/_generated/api/recipients/get_recipient.py +252 -0
  95. honeycomb/_generated/api/recipients/list_recipients.py +230 -0
  96. honeycomb/_generated/api/recipients/update_recipient.py +323 -0
  97. honeycomb/_generated/api/reporting/__init__.py +0 -0
  98. honeycomb/_generated/api/reporting/get_slo_history.py +218 -0
  99. honeycomb/_generated/api/service_maps/__init__.py +0 -0
  100. honeycomb/_generated/api/service_maps/create_map_dependency_request.py +252 -0
  101. honeycomb/_generated/api/service_maps/get_map_dependencies.py +265 -0
  102. honeycomb/_generated/api/sl_os/__init__.py +0 -0
  103. honeycomb/_generated/api/sl_os/create_slo.py +229 -0
  104. honeycomb/_generated/api/sl_os/delete_slo.py +210 -0
  105. honeycomb/_generated/api/sl_os/get_slo.py +256 -0
  106. honeycomb/_generated/api/sl_os/list_slos.py +210 -0
  107. honeycomb/_generated/api/sl_os/update_slo.py +242 -0
  108. honeycomb/_generated/api/triggers/__init__.py +0 -0
  109. honeycomb/_generated/api/triggers/create_trigger.py +250 -0
  110. honeycomb/_generated/api/triggers/delete_trigger.py +204 -0
  111. honeycomb/_generated/api/triggers/get_trigger.py +214 -0
  112. honeycomb/_generated/api/triggers/list_triggers.py +206 -0
  113. honeycomb/_generated/api/triggers/list_triggers_with_recipient.py +208 -0
  114. honeycomb/_generated/api/triggers/update_trigger.py +248 -0
  115. honeycomb/_generated/client.py +271 -0
  116. honeycomb/_generated/errors.py +14 -0
  117. honeycomb/_generated/models/__init__.py +561 -0
  118. honeycomb/_generated/models/api_key_create_request.py +78 -0
  119. honeycomb/_generated/models/api_key_create_request_data.py +130 -0
  120. honeycomb/_generated/models/api_key_create_request_data_relationships.py +78 -0
  121. honeycomb/_generated/models/api_key_create_request_data_type.py +7 -0
  122. honeycomb/_generated/models/api_key_list_response.py +112 -0
  123. honeycomb/_generated/models/api_key_object.py +189 -0
  124. honeycomb/_generated/models/api_key_object_links.py +74 -0
  125. honeycomb/_generated/models/api_key_object_relationships.py +150 -0
  126. honeycomb/_generated/models/api_key_object_type.py +7 -0
  127. honeycomb/_generated/models/api_key_response.py +78 -0
  128. honeycomb/_generated/models/api_key_update_request.py +104 -0
  129. honeycomb/_generated/models/auth.py +140 -0
  130. honeycomb/_generated/models/auth_api_key_access.py +154 -0
  131. honeycomb/_generated/models/auth_environment.py +82 -0
  132. honeycomb/_generated/models/auth_team.py +82 -0
  133. honeycomb/_generated/models/auth_type.py +8 -0
  134. honeycomb/_generated/models/auth_v2_response.py +108 -0
  135. honeycomb/_generated/models/auth_v2_response_data.py +122 -0
  136. honeycomb/_generated/models/auth_v2_response_data_attributes.py +141 -0
  137. honeycomb/_generated/models/auth_v2_response_data_attributes_key_type.py +7 -0
  138. honeycomb/_generated/models/auth_v2_response_data_attributes_timestamps.py +107 -0
  139. honeycomb/_generated/models/auth_v2_response_data_relationships.py +59 -0
  140. honeycomb/_generated/models/auth_v2_response_data_type.py +7 -0
  141. honeycomb/_generated/models/base_trigger.py +367 -0
  142. honeycomb/_generated/models/base_trigger_alert_type.py +8 -0
  143. honeycomb/_generated/models/base_trigger_baseline_details_type_0.py +92 -0
  144. honeycomb/_generated/models/base_trigger_baseline_details_type_0_offset_minutes.py +10 -0
  145. honeycomb/_generated/models/base_trigger_baseline_details_type_0_type.py +8 -0
  146. honeycomb/_generated/models/base_trigger_evaluation_schedule.py +83 -0
  147. honeycomb/_generated/models/base_trigger_evaluation_schedule_type.py +8 -0
  148. honeycomb/_generated/models/base_trigger_evaluation_schedule_window.py +103 -0
  149. honeycomb/_generated/models/base_trigger_evaluation_schedule_window_days_of_week_item.py +13 -0
  150. honeycomb/_generated/models/base_trigger_threshold.py +95 -0
  151. honeycomb/_generated/models/base_trigger_threshold_op.py +10 -0
  152. honeycomb/_generated/models/batch_event.py +110 -0
  153. honeycomb/_generated/models/board.py +276 -0
  154. honeycomb/_generated/models/board_layout_generation.py +8 -0
  155. honeycomb/_generated/models/board_links.py +74 -0
  156. honeycomb/_generated/models/board_panel_position.py +104 -0
  157. honeycomb/_generated/models/board_query_visualization_settings.py +141 -0
  158. honeycomb/_generated/models/board_query_visualization_settings_charts_item.py +113 -0
  159. honeycomb/_generated/models/board_query_visualization_settings_charts_item_chart_type.py +13 -0
  160. honeycomb/_generated/models/board_type.py +7 -0
  161. honeycomb/_generated/models/board_view_filter.py +93 -0
  162. honeycomb/_generated/models/board_view_filter_operation.py +22 -0
  163. honeycomb/_generated/models/board_view_response.py +111 -0
  164. honeycomb/_generated/models/budget_rate.py +189 -0
  165. honeycomb/_generated/models/budget_rate_alert_type.py +8 -0
  166. honeycomb/_generated/models/burn_alert_shared_params.py +136 -0
  167. honeycomb/_generated/models/calculated_field.py +117 -0
  168. honeycomb/_generated/models/configuration_key_attributes.py +140 -0
  169. honeycomb/_generated/models/configuration_key_attributes_key_type.py +7 -0
  170. honeycomb/_generated/models/configuration_key_attributes_timestamps.py +107 -0
  171. honeycomb/_generated/models/create_board_view_request.py +96 -0
  172. honeycomb/_generated/models/create_budget_rate_burn_alert_request.py +232 -0
  173. honeycomb/_generated/models/create_budget_rate_burn_alert_request_slo.py +74 -0
  174. honeycomb/_generated/models/create_column.py +149 -0
  175. honeycomb/_generated/models/create_column_type.py +11 -0
  176. honeycomb/_generated/models/create_enhance_indexer_usage_record_request.py +78 -0
  177. honeycomb/_generated/models/create_enhance_indexer_usage_record_request_data.py +90 -0
  178. honeycomb/_generated/models/create_enhance_indexer_usage_record_request_data_attributes.py +97 -0
  179. honeycomb/_generated/models/create_enhance_indexer_usage_record_request_data_attributes_usage_data.py +88 -0
  180. honeycomb/_generated/models/create_enhance_indexer_usage_record_request_data_attributes_usage_data_resource_metrics_item.py +89 -0
  181. honeycomb/_generated/models/create_enhance_indexer_usage_record_request_data_attributes_usage_data_resource_metrics_item_scope_metrics_item.py +89 -0
  182. honeycomb/_generated/models/create_enhance_indexer_usage_record_request_data_attributes_usage_data_resource_metrics_item_scope_metrics_item_metrics_item.py +97 -0
  183. honeycomb/_generated/models/create_enhance_indexer_usage_record_request_data_attributes_usage_data_resource_metrics_item_scope_metrics_item_metrics_item_sum.py +102 -0
  184. honeycomb/_generated/models/create_enhance_indexer_usage_record_request_data_attributes_usage_data_resource_metrics_item_scope_metrics_item_metrics_item_sum_aggregation_temporality.py +7 -0
  185. honeycomb/_generated/models/create_enhance_indexer_usage_record_request_data_attributes_usage_data_resource_metrics_item_scope_metrics_item_metrics_item_sum_datapoints_item.py +105 -0
  186. honeycomb/_generated/models/create_enhance_indexer_usage_record_request_data_attributes_usage_data_resource_metrics_item_scope_metrics_item_metrics_item_sum_datapoints_item_attributes_item.py +87 -0
  187. honeycomb/_generated/models/create_enhance_indexer_usage_record_request_data_attributes_usage_data_resource_metrics_item_scope_metrics_item_metrics_item_sum_datapoints_item_attributes_item_value.py +73 -0
  188. honeycomb/_generated/models/create_enhance_indexer_usage_record_request_data_type.py +7 -0
  189. honeycomb/_generated/models/create_environment_request.py +78 -0
  190. honeycomb/_generated/models/create_environment_request_data.py +90 -0
  191. honeycomb/_generated/models/create_environment_request_data_attributes.py +102 -0
  192. honeycomb/_generated/models/create_environment_request_data_type.py +7 -0
  193. honeycomb/_generated/models/create_events_content_encoding.py +8 -0
  194. honeycomb/_generated/models/create_events_response_200_item.py +82 -0
  195. honeycomb/_generated/models/create_exhaustion_time_burn_alert_request.py +217 -0
  196. honeycomb/_generated/models/create_exhaustion_time_burn_alert_request_slo.py +74 -0
  197. honeycomb/_generated/models/create_map_dependencies_request.py +128 -0
  198. honeycomb/_generated/models/create_map_dependencies_response.py +97 -0
  199. honeycomb/_generated/models/create_map_dependencies_response_status.py +9 -0
  200. honeycomb/_generated/models/create_pipeline_health_record_request.py +78 -0
  201. honeycomb/_generated/models/create_pipeline_health_record_request_data.py +98 -0
  202. honeycomb/_generated/models/create_pipeline_health_record_request_data_attributes.py +88 -0
  203. honeycomb/_generated/models/create_pipeline_health_record_request_data_attributes_usage_data.py +88 -0
  204. honeycomb/_generated/models/create_pipeline_health_record_request_data_attributes_usage_data_resource_metrics_item.py +89 -0
  205. honeycomb/_generated/models/create_pipeline_health_record_request_data_attributes_usage_data_resource_metrics_item_scope_metrics_item.py +89 -0
  206. honeycomb/_generated/models/create_pipeline_health_record_request_data_attributes_usage_data_resource_metrics_item_scope_metrics_item_metrics_item.py +97 -0
  207. honeycomb/_generated/models/create_pipeline_health_record_request_data_attributes_usage_data_resource_metrics_item_scope_metrics_item_metrics_item_sum.py +102 -0
  208. honeycomb/_generated/models/create_pipeline_health_record_request_data_attributes_usage_data_resource_metrics_item_scope_metrics_item_metrics_item_sum_aggregation_temporality.py +7 -0
  209. honeycomb/_generated/models/create_pipeline_health_record_request_data_attributes_usage_data_resource_metrics_item_scope_metrics_item_metrics_item_sum_datapoints_item.py +105 -0
  210. honeycomb/_generated/models/create_pipeline_health_record_request_data_attributes_usage_data_resource_metrics_item_scope_metrics_item_metrics_item_sum_datapoints_item_attributes_item.py +87 -0
  211. honeycomb/_generated/models/create_pipeline_health_record_request_data_attributes_usage_data_resource_metrics_item_scope_metrics_item_metrics_item_sum_datapoints_item_attributes_item_value.py +73 -0
  212. honeycomb/_generated/models/create_pipeline_health_record_request_data_type.py +7 -0
  213. honeycomb/_generated/models/create_query_result_request.py +118 -0
  214. honeycomb/_generated/models/dataset.py +183 -0
  215. honeycomb/_generated/models/dataset_creation_payload.py +93 -0
  216. honeycomb/_generated/models/dataset_definition_type_1.py +96 -0
  217. honeycomb/_generated/models/dataset_definition_type_1_column_type.py +8 -0
  218. honeycomb/_generated/models/dataset_definitions.py +599 -0
  219. honeycomb/_generated/models/dataset_relationship.py +79 -0
  220. honeycomb/_generated/models/dataset_relationship_data.py +82 -0
  221. honeycomb/_generated/models/dataset_relationship_data_type.py +7 -0
  222. honeycomb/_generated/models/dataset_settings.py +73 -0
  223. honeycomb/_generated/models/dataset_update_payload.py +105 -0
  224. honeycomb/_generated/models/dataset_update_payload_settings.py +73 -0
  225. honeycomb/_generated/models/detailed_error.py +115 -0
  226. honeycomb/_generated/models/email_recipient.py +160 -0
  227. honeycomb/_generated/models/email_recipient_details.py +71 -0
  228. honeycomb/_generated/models/email_recipient_type.py +7 -0
  229. honeycomb/_generated/models/environment.py +112 -0
  230. honeycomb/_generated/models/environment_attributes.py +140 -0
  231. honeycomb/_generated/models/environment_attributes_color_type_1.py +7 -0
  232. honeycomb/_generated/models/environment_attributes_settings.py +70 -0
  233. honeycomb/_generated/models/environment_color.py +16 -0
  234. honeycomb/_generated/models/environment_links.py +70 -0
  235. honeycomb/_generated/models/environment_list_response.py +112 -0
  236. honeycomb/_generated/models/environment_relationship.py +79 -0
  237. honeycomb/_generated/models/environment_relationship_data.py +82 -0
  238. honeycomb/_generated/models/environment_relationship_data_type.py +7 -0
  239. honeycomb/_generated/models/environment_response.py +78 -0
  240. honeycomb/_generated/models/environment_type.py +7 -0
  241. honeycomb/_generated/models/error.py +74 -0
  242. honeycomb/_generated/models/event.py +71 -0
  243. honeycomb/_generated/models/exhaustion_time.py +174 -0
  244. honeycomb/_generated/models/exhaustion_time_alert_type.py +8 -0
  245. honeycomb/_generated/models/exhaustion_time_burn_alert_list_response.py +198 -0
  246. honeycomb/_generated/models/exhaustion_time_burn_alert_list_response_slo.py +77 -0
  247. honeycomb/_generated/models/filter_op.py +22 -0
  248. honeycomb/_generated/models/get_map_dependencies_response.py +169 -0
  249. honeycomb/_generated/models/get_map_dependencies_response_status.py +9 -0
  250. honeycomb/_generated/models/having_calculate_op.py +29 -0
  251. honeycomb/_generated/models/having_op.py +12 -0
  252. honeycomb/_generated/models/included_resource.py +106 -0
  253. honeycomb/_generated/models/included_resource_attributes.py +62 -0
  254. honeycomb/_generated/models/ingest_key_attributes.py +153 -0
  255. honeycomb/_generated/models/ingest_key_attributes_key_type.py +7 -0
  256. honeycomb/_generated/models/ingest_key_attributes_permissions.py +74 -0
  257. honeycomb/_generated/models/ingest_key_attributes_timestamps.py +107 -0
  258. honeycomb/_generated/models/ingest_key_type.py +90 -0
  259. honeycomb/_generated/models/ingest_key_type_key_type.py +7 -0
  260. honeycomb/_generated/models/jsonapi_error_source.py +92 -0
  261. honeycomb/_generated/models/kinesis_event.py +111 -0
  262. honeycomb/_generated/models/kinesis_event_record.py +73 -0
  263. honeycomb/_generated/models/kinesis_response.py +91 -0
  264. honeycomb/_generated/models/list_api_keys_filtertype.py +8 -0
  265. honeycomb/_generated/models/map_dependency.py +118 -0
  266. honeycomb/_generated/models/map_node.py +97 -0
  267. honeycomb/_generated/models/map_node_type.py +7 -0
  268. honeycomb/_generated/models/marker.py +151 -0
  269. honeycomb/_generated/models/marker_create_request.py +78 -0
  270. honeycomb/_generated/models/marker_create_request_data.py +104 -0
  271. honeycomb/_generated/models/marker_create_request_data_attributes.py +110 -0
  272. honeycomb/_generated/models/marker_create_request_data_relationships.py +92 -0
  273. honeycomb/_generated/models/marker_create_request_data_type.py +7 -0
  274. honeycomb/_generated/models/marker_object.py +136 -0
  275. honeycomb/_generated/models/marker_object_attributes.py +146 -0
  276. honeycomb/_generated/models/marker_object_attributes_timestamps.py +107 -0
  277. honeycomb/_generated/models/marker_object_links.py +74 -0
  278. honeycomb/_generated/models/marker_object_relationships.py +111 -0
  279. honeycomb/_generated/models/marker_object_relationships_dataset.py +104 -0
  280. honeycomb/_generated/models/marker_object_relationships_dataset_data_type_0.py +94 -0
  281. honeycomb/_generated/models/marker_object_relationships_dataset_data_type_0_type.py +7 -0
  282. honeycomb/_generated/models/marker_object_type.py +7 -0
  283. honeycomb/_generated/models/marker_response.py +78 -0
  284. honeycomb/_generated/models/marker_setting.py +125 -0
  285. honeycomb/_generated/models/marker_update_request.py +78 -0
  286. honeycomb/_generated/models/marker_update_request_data.py +104 -0
  287. honeycomb/_generated/models/marker_update_request_data_attributes.py +111 -0
  288. honeycomb/_generated/models/marker_update_request_data_relationships.py +92 -0
  289. honeycomb/_generated/models/marker_update_request_data_type.py +7 -0
  290. honeycomb/_generated/models/ms_teams_recipient.py +161 -0
  291. honeycomb/_generated/models/ms_teams_recipient_details.py +80 -0
  292. honeycomb/_generated/models/ms_teams_recipient_type.py +7 -0
  293. honeycomb/_generated/models/ms_teams_workflow_recipient.py +161 -0
  294. honeycomb/_generated/models/ms_teams_workflow_recipient_details.py +80 -0
  295. honeycomb/_generated/models/ms_teams_workflow_recipient_type.py +7 -0
  296. honeycomb/_generated/models/notification_recipient.py +131 -0
  297. honeycomb/_generated/models/notification_recipient_details.py +117 -0
  298. honeycomb/_generated/models/notification_recipient_details_pagerduty_severity.py +10 -0
  299. honeycomb/_generated/models/notification_recipient_details_variables_item.py +81 -0
  300. honeycomb/_generated/models/pager_duty_recipient.py +160 -0
  301. honeycomb/_generated/models/pager_duty_recipient_details.py +79 -0
  302. honeycomb/_generated/models/pager_duty_recipient_type.py +7 -0
  303. honeycomb/_generated/models/pagination_links.py +80 -0
  304. honeycomb/_generated/models/payload_template.py +73 -0
  305. honeycomb/_generated/models/pipeline_configuration_response.py +112 -0
  306. honeycomb/_generated/models/pipeline_configuration_response_attributes.py +101 -0
  307. honeycomb/_generated/models/pipeline_configuration_response_attributes_configs_item.py +85 -0
  308. honeycomb/_generated/models/pipeline_configuration_response_links.py +73 -0
  309. honeycomb/_generated/models/pipeline_configuration_response_type.py +7 -0
  310. honeycomb/_generated/models/pipeline_configuration_rollout.py +112 -0
  311. honeycomb/_generated/models/pipeline_configuration_rollout_attributes.py +75 -0
  312. honeycomb/_generated/models/pipeline_configuration_rollout_attributes_status.py +12 -0
  313. honeycomb/_generated/models/pipeline_configuration_rollout_links.py +73 -0
  314. honeycomb/_generated/models/pipeline_configuration_rollout_type.py +7 -0
  315. honeycomb/_generated/models/preset_filter.py +78 -0
  316. honeycomb/_generated/models/query.py +346 -0
  317. honeycomb/_generated/models/query_annotation.py +166 -0
  318. honeycomb/_generated/models/query_annotation_source.py +8 -0
  319. honeycomb/_generated/models/query_calculated_fields_item.py +80 -0
  320. honeycomb/_generated/models/query_calculations_item.py +98 -0
  321. honeycomb/_generated/models/query_compare_time_offset_seconds.py +14 -0
  322. honeycomb/_generated/models/query_filter_combination.py +8 -0
  323. honeycomb/_generated/models/query_filters_item.py +126 -0
  324. honeycomb/_generated/models/query_havings_item.py +128 -0
  325. honeycomb/_generated/models/query_op.py +30 -0
  326. honeycomb/_generated/models/query_orders_item.py +115 -0
  327. honeycomb/_generated/models/query_orders_item_order.py +8 -0
  328. honeycomb/_generated/models/query_panel.py +114 -0
  329. honeycomb/_generated/models/query_panel_query_panel.py +143 -0
  330. honeycomb/_generated/models/query_panel_query_panel_query_style.py +9 -0
  331. honeycomb/_generated/models/query_result.py +130 -0
  332. honeycomb/_generated/models/query_result_details.py +156 -0
  333. honeycomb/_generated/models/query_result_details_data.py +188 -0
  334. honeycomb/_generated/models/query_result_details_links.py +85 -0
  335. honeycomb/_generated/models/query_result_links.py +85 -0
  336. honeycomb/_generated/models/query_results_data.py +89 -0
  337. honeycomb/_generated/models/query_results_data_data.py +71 -0
  338. honeycomb/_generated/models/query_results_series.py +97 -0
  339. honeycomb/_generated/models/recipient_properties.py +137 -0
  340. honeycomb/_generated/models/recipient_type.py +12 -0
  341. honeycomb/_generated/models/slack_recipient.py +160 -0
  342. honeycomb/_generated/models/slack_recipient_details.py +71 -0
  343. honeycomb/_generated/models/slack_recipient_type.py +7 -0
  344. honeycomb/_generated/models/slo.py +245 -0
  345. honeycomb/_generated/models/slo_create.py +245 -0
  346. honeycomb/_generated/models/slo_create_sli.py +75 -0
  347. honeycomb/_generated/models/slo_detailed_response.py +312 -0
  348. honeycomb/_generated/models/slo_detailed_response_status.py +10 -0
  349. honeycomb/_generated/models/slo_history.py +94 -0
  350. honeycomb/_generated/models/slo_history_request.py +93 -0
  351. honeycomb/_generated/models/slo_history_response.py +91 -0
  352. honeycomb/_generated/models/slo_panel.py +114 -0
  353. honeycomb/_generated/models/slo_panel_slo_panel.py +75 -0
  354. honeycomb/_generated/models/slo_sli.py +74 -0
  355. honeycomb/_generated/models/tag.py +79 -0
  356. honeycomb/_generated/models/team_relationship.py +78 -0
  357. honeycomb/_generated/models/team_relationship_team.py +78 -0
  358. honeycomb/_generated/models/team_relationship_team_data.py +82 -0
  359. honeycomb/_generated/models/team_relationship_team_data_type.py +7 -0
  360. honeycomb/_generated/models/template_variable_definition.py +81 -0
  361. honeycomb/_generated/models/text_panel.py +114 -0
  362. honeycomb/_generated/models/text_panel_text_panel.py +71 -0
  363. honeycomb/_generated/models/trigger_response.py +399 -0
  364. honeycomb/_generated/models/trigger_with_inline_query.py +390 -0
  365. honeycomb/_generated/models/trigger_with_inline_query_query.py +60 -0
  366. honeycomb/_generated/models/trigger_with_query_reference.py +376 -0
  367. honeycomb/_generated/models/update_board_view_request.py +107 -0
  368. honeycomb/_generated/models/update_environment_request.py +78 -0
  369. honeycomb/_generated/models/update_environment_request_data.py +98 -0
  370. honeycomb/_generated/models/update_environment_request_data_attributes.py +118 -0
  371. honeycomb/_generated/models/update_environment_request_data_attributes_settings.py +73 -0
  372. honeycomb/_generated/models/update_environment_request_data_type.py +7 -0
  373. honeycomb/_generated/models/update_exhaustion_time_burn_alert_request.py +202 -0
  374. honeycomb/_generated/models/update_pipeline_configuration_rollout.py +98 -0
  375. honeycomb/_generated/models/update_pipeline_configuration_rollout_attributes.py +75 -0
  376. honeycomb/_generated/models/update_pipeline_configuration_rollout_attributes_status.py +12 -0
  377. honeycomb/_generated/models/update_pipeline_configuration_rollout_request.py +78 -0
  378. honeycomb/_generated/models/update_pipeline_configuration_rollout_request_data.py +98 -0
  379. honeycomb/_generated/models/update_pipeline_configuration_rollout_request_data_attributes.py +75 -0
  380. honeycomb/_generated/models/update_pipeline_configuration_rollout_request_data_attributes_status.py +12 -0
  381. honeycomb/_generated/models/update_pipeline_configuration_rollout_request_data_type.py +7 -0
  382. honeycomb/_generated/models/update_pipeline_configuration_rollout_response.py +78 -0
  383. honeycomb/_generated/models/update_pipeline_configuration_rollout_type.py +7 -0
  384. honeycomb/_generated/models/user_relationship.py +78 -0
  385. honeycomb/_generated/models/user_relationship_data.py +82 -0
  386. honeycomb/_generated/models/user_relationship_data_type.py +7 -0
  387. honeycomb/_generated/models/validation_error.py +145 -0
  388. honeycomb/_generated/models/validation_error_type_detail_item.py +103 -0
  389. honeycomb/_generated/models/validation_error_type_detail_item_code.py +10 -0
  390. honeycomb/_generated/models/webhook_header.py +81 -0
  391. honeycomb/_generated/models/webhook_recipient.py +160 -0
  392. honeycomb/_generated/models/webhook_recipient_details.py +142 -0
  393. honeycomb/_generated/models/webhook_recipient_details_webhook_payloads.py +117 -0
  394. honeycomb/_generated/models/webhook_recipient_details_webhook_payloads_payload_templates.py +126 -0
  395. honeycomb/_generated/models/webhook_recipient_type.py +7 -0
  396. honeycomb/_generated/py.typed +1 -0
  397. honeycomb/_generated/types.py +46 -0
  398. honeycomb/auth.py +152 -0
  399. honeycomb/client.py +736 -0
  400. honeycomb/exceptions.py +236 -0
  401. honeycomb/models/__init__.py +157 -0
  402. honeycomb/models/api_keys.py +81 -0
  403. honeycomb/models/board_builder.py +387 -0
  404. honeycomb/models/boards.py +86 -0
  405. honeycomb/models/burn_alerts.py +124 -0
  406. honeycomb/models/columns.py +59 -0
  407. honeycomb/models/datasets.py +51 -0
  408. honeycomb/models/derived_columns.py +107 -0
  409. honeycomb/models/environments.py +106 -0
  410. honeycomb/models/events.py +35 -0
  411. honeycomb/models/marker_builder.py +136 -0
  412. honeycomb/models/markers.py +73 -0
  413. honeycomb/models/queries.py +210 -0
  414. honeycomb/models/query_annotations.py +63 -0
  415. honeycomb/models/query_builder.py +840 -0
  416. honeycomb/models/recipient_builder.py +248 -0
  417. honeycomb/models/recipients.py +43 -0
  418. honeycomb/models/service_map_dependencies.py +126 -0
  419. honeycomb/models/slo_builder.py +463 -0
  420. honeycomb/models/slos.py +66 -0
  421. honeycomb/models/tags_mixin.py +79 -0
  422. honeycomb/models/trigger_builder.py +561 -0
  423. honeycomb/models/triggers.py +208 -0
  424. honeycomb/resources/__init__.py +35 -0
  425. honeycomb/resources/_recipient_utils.py +156 -0
  426. honeycomb/resources/api_keys.py +303 -0
  427. honeycomb/resources/base.py +142 -0
  428. honeycomb/resources/boards.py +350 -0
  429. honeycomb/resources/burn_alerts.py +205 -0
  430. honeycomb/resources/columns.py +185 -0
  431. honeycomb/resources/datasets.py +163 -0
  432. honeycomb/resources/derived_columns.py +233 -0
  433. honeycomb/resources/environments.py +295 -0
  434. honeycomb/resources/events.py +156 -0
  435. honeycomb/resources/markers.py +334 -0
  436. honeycomb/resources/queries.py +256 -0
  437. honeycomb/resources/query_annotations.py +207 -0
  438. honeycomb/resources/query_results.py +886 -0
  439. honeycomb/resources/recipients.py +202 -0
  440. honeycomb/resources/service_map_dependencies.py +389 -0
  441. honeycomb/resources/slos.py +353 -0
  442. honeycomb/resources/triggers.py +284 -0
  443. honeycomb/tools/__init__.py +85 -0
  444. honeycomb/tools/__main__.py +204 -0
  445. honeycomb/tools/builders.py +512 -0
  446. honeycomb/tools/descriptions.py +523 -0
  447. honeycomb/tools/executor.py +860 -0
  448. honeycomb/tools/generator.py +2386 -0
  449. honeycomb/tools/schemas.py +184 -0
  450. honeycomb_api-0.1.0.dist-info/METADATA +451 -0
  451. honeycomb_api-0.1.0.dist-info/RECORD +453 -0
  452. honeycomb_api-0.1.0.dist-info/WHEEL +4 -0
  453. honeycomb_api-0.1.0.dist-info/licenses/LICENSE +21 -0
honeycomb/client.py ADDED
@@ -0,0 +1,736 @@
1
+ """Honeycomb API client with async-first design and sync wrapper."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import asyncio
6
+ from contextlib import suppress
7
+ from dataclasses import dataclass
8
+ from datetime import datetime
9
+ from email.utils import parsedate_to_datetime
10
+ from typing import TYPE_CHECKING, Any
11
+
12
+ import httpx
13
+
14
+ from .auth import create_auth
15
+ from .exceptions import (
16
+ HoneycombAPIError,
17
+ HoneycombAuthError,
18
+ HoneycombConnectionError,
19
+ HoneycombForbiddenError,
20
+ HoneycombNotFoundError,
21
+ HoneycombRateLimitError,
22
+ HoneycombServerError,
23
+ HoneycombTimeoutError,
24
+ HoneycombValidationError,
25
+ )
26
+
27
+ if TYPE_CHECKING:
28
+ from .resources.api_keys import ApiKeysResource
29
+ from .resources.boards import BoardsResource
30
+ from .resources.burn_alerts import BurnAlertsResource
31
+ from .resources.columns import ColumnsResource
32
+ from .resources.datasets import DatasetsResource
33
+ from .resources.derived_columns import DerivedColumnsResource
34
+ from .resources.environments import EnvironmentsResource
35
+ from .resources.events import EventsResource
36
+ from .resources.markers import MarkersResource
37
+ from .resources.queries import QueriesResource
38
+ from .resources.query_annotations import QueryAnnotationsResource
39
+ from .resources.query_results import QueryResultsResource
40
+ from .resources.recipients import RecipientsResource
41
+ from .resources.service_map_dependencies import ServiceMapDependenciesResource
42
+ from .resources.slos import SLOsResource
43
+ from .resources.triggers import TriggersResource
44
+
45
+
46
+ DEFAULT_BASE_URL = "https://api.honeycomb.io"
47
+ DEFAULT_TIMEOUT = 30.0
48
+ DEFAULT_MAX_RETRIES = 3
49
+
50
+
51
+ @dataclass
52
+ class RetryConfig:
53
+ """Configuration for retry behavior.
54
+
55
+ Attributes:
56
+ max_retries: Maximum number of retry attempts.
57
+ base_delay: Base delay in seconds for exponential backoff.
58
+ max_delay: Maximum delay in seconds between retries.
59
+ exponential_base: Base for exponential backoff calculation.
60
+ retry_statuses: HTTP status codes that should trigger a retry.
61
+ """
62
+
63
+ max_retries: int = 3
64
+ base_delay: float = 1.0
65
+ max_delay: float = 30.0
66
+ exponential_base: float = 2.0
67
+ retry_statuses: set[int] = None # type: ignore
68
+
69
+ def __post_init__(self) -> None:
70
+ """Initialize default retry statuses if not provided."""
71
+ if self.retry_statuses is None:
72
+ self.retry_statuses = {429, 500, 502, 503, 504}
73
+
74
+
75
+ @dataclass
76
+ class RateLimitInfo:
77
+ """Rate limit information from response headers.
78
+
79
+ Attributes:
80
+ limit: Total requests allowed in the time window.
81
+ remaining: Remaining requests in the current time window.
82
+ reset: Seconds until the rate limit resets.
83
+ """
84
+
85
+ limit: int | None = None
86
+ remaining: int | None = None
87
+ reset: int | None = None
88
+
89
+
90
+ class HoneycombClient:
91
+ """Async-first client for the Honeycomb API.
92
+
93
+ Supports both async and sync usage patterns.
94
+
95
+ Example (async - recommended):
96
+ >>> async with HoneycombClient(api_key="your-key") as client:
97
+ ... datasets = await client.datasets.list()
98
+ ... triggers = await client.triggers.list(dataset="my-dataset")
99
+
100
+ Example (sync):
101
+ >>> with HoneycombClient(api_key="your-key", sync=True) as client:
102
+ ... datasets = client.datasets.list()
103
+
104
+ Args:
105
+ api_key: Honeycomb API key for single-environment access.
106
+ management_key: Management API key ID for multi-environment access.
107
+ management_secret: Management API key secret.
108
+ base_url: API base URL (default: https://api.honeycomb.io).
109
+ timeout: Request timeout in seconds (default: 30).
110
+ max_retries: Maximum retry attempts for failed requests (default: 3).
111
+ retry_config: Custom retry configuration (optional, overrides max_retries).
112
+ sync: If True, use synchronous HTTP client (default: False).
113
+ """
114
+
115
+ def __init__(
116
+ self,
117
+ *,
118
+ api_key: str | None = None,
119
+ management_key: str | None = None,
120
+ management_secret: str | None = None,
121
+ base_url: str = DEFAULT_BASE_URL,
122
+ timeout: float = DEFAULT_TIMEOUT,
123
+ max_retries: int = DEFAULT_MAX_RETRIES,
124
+ retry_config: RetryConfig | None = None,
125
+ sync: bool = False,
126
+ ) -> None:
127
+ self._auth = create_auth(
128
+ api_key=api_key,
129
+ management_key=management_key,
130
+ management_secret=management_secret,
131
+ )
132
+ self._base_url = base_url.rstrip("/")
133
+ self._timeout = timeout
134
+ self._max_retries = max_retries
135
+ self._retry_config = retry_config or RetryConfig(max_retries=max_retries)
136
+ self._sync_mode = sync
137
+
138
+ # HTTP clients (lazily initialized)
139
+ self._async_client: httpx.AsyncClient | None = None
140
+ self._sync_client: httpx.Client | None = None
141
+
142
+ # Resource instances (lazily initialized)
143
+ self._triggers: TriggersResource | None = None
144
+ self._slos: SLOsResource | None = None
145
+ self._datasets: DatasetsResource | None = None
146
+ self._boards: BoardsResource | None = None
147
+ self._queries: QueriesResource | None = None
148
+ self._query_annotations: QueryAnnotationsResource | None = None
149
+ self._query_results: QueryResultsResource | None = None
150
+ self._columns: ColumnsResource | None = None
151
+ self._derived_columns: DerivedColumnsResource | None = None
152
+ self._markers: MarkersResource | None = None
153
+ self._recipients: RecipientsResource | None = None
154
+ self._burn_alerts: BurnAlertsResource | None = None
155
+ self._events: EventsResource | None = None
156
+ self._api_keys: ApiKeysResource | None = None
157
+ self._environments: EnvironmentsResource | None = None
158
+ self._service_map_dependencies: ServiceMapDependenciesResource | None = None
159
+
160
+ # -------------------------------------------------------------------------
161
+ # Resource accessors
162
+ # -------------------------------------------------------------------------
163
+
164
+ @property
165
+ def triggers(self) -> TriggersResource:
166
+ """Access the Triggers API."""
167
+ if self._triggers is None:
168
+ from .resources.triggers import TriggersResource
169
+
170
+ self._triggers = TriggersResource(self)
171
+ return self._triggers
172
+
173
+ @property
174
+ def slos(self) -> SLOsResource:
175
+ """Access the SLOs API."""
176
+ if self._slos is None:
177
+ from .resources.slos import SLOsResource
178
+
179
+ self._slos = SLOsResource(self)
180
+ return self._slos
181
+
182
+ @property
183
+ def datasets(self) -> DatasetsResource:
184
+ """Access the Datasets API."""
185
+ if self._datasets is None:
186
+ from .resources.datasets import DatasetsResource
187
+
188
+ self._datasets = DatasetsResource(self)
189
+ return self._datasets
190
+
191
+ @property
192
+ def boards(self) -> BoardsResource:
193
+ """Access the Boards API."""
194
+ if self._boards is None:
195
+ from .resources.boards import BoardsResource
196
+
197
+ self._boards = BoardsResource(self)
198
+ return self._boards
199
+
200
+ @property
201
+ def queries(self) -> QueriesResource:
202
+ """Access the Queries API."""
203
+ if self._queries is None:
204
+ from .resources.queries import QueriesResource
205
+
206
+ self._queries = QueriesResource(self)
207
+ return self._queries
208
+
209
+ @property
210
+ def query_annotations(self) -> QueryAnnotationsResource:
211
+ """Access the Query Annotations API."""
212
+ if self._query_annotations is None:
213
+ from .resources.query_annotations import QueryAnnotationsResource
214
+
215
+ self._query_annotations = QueryAnnotationsResource(self)
216
+ return self._query_annotations
217
+
218
+ @property
219
+ def query_results(self) -> QueryResultsResource:
220
+ """Access the Query Results API."""
221
+ if self._query_results is None:
222
+ from .resources.query_results import QueryResultsResource
223
+
224
+ self._query_results = QueryResultsResource(self)
225
+ return self._query_results
226
+
227
+ @property
228
+ def columns(self) -> ColumnsResource:
229
+ """Access the Columns API."""
230
+ if self._columns is None:
231
+ from .resources.columns import ColumnsResource
232
+
233
+ self._columns = ColumnsResource(self)
234
+ return self._columns
235
+
236
+ @property
237
+ def derived_columns(self) -> DerivedColumnsResource:
238
+ """Access the Derived Columns (Calculated Fields) API."""
239
+ if self._derived_columns is None:
240
+ from .resources.derived_columns import DerivedColumnsResource
241
+
242
+ self._derived_columns = DerivedColumnsResource(self)
243
+ return self._derived_columns
244
+
245
+ @property
246
+ def markers(self) -> MarkersResource:
247
+ """Access the Markers API."""
248
+ if self._markers is None:
249
+ from .resources.markers import MarkersResource
250
+
251
+ self._markers = MarkersResource(self)
252
+ return self._markers
253
+
254
+ @property
255
+ def recipients(self) -> RecipientsResource:
256
+ """Access the Recipients API."""
257
+ if self._recipients is None:
258
+ from .resources.recipients import RecipientsResource
259
+
260
+ self._recipients = RecipientsResource(self)
261
+ return self._recipients
262
+
263
+ @property
264
+ def burn_alerts(self) -> BurnAlertsResource:
265
+ """Access the Burn Alerts API."""
266
+ if self._burn_alerts is None:
267
+ from .resources.burn_alerts import BurnAlertsResource
268
+
269
+ self._burn_alerts = BurnAlertsResource(self)
270
+ return self._burn_alerts
271
+
272
+ @property
273
+ def events(self) -> EventsResource:
274
+ """Access the Events API (data ingestion)."""
275
+ if self._events is None:
276
+ from .resources.events import EventsResource
277
+
278
+ self._events = EventsResource(self)
279
+ return self._events
280
+
281
+ @property
282
+ def api_keys(self) -> ApiKeysResource:
283
+ """Access the API Keys API (v2 team-scoped)."""
284
+ if self._api_keys is None:
285
+ from .resources.api_keys import ApiKeysResource
286
+
287
+ self._api_keys = ApiKeysResource(self)
288
+ return self._api_keys
289
+
290
+ @property
291
+ def environments(self) -> EnvironmentsResource:
292
+ """Access the Environments API (v2 team-scoped)."""
293
+ if self._environments is None:
294
+ from .resources.environments import EnvironmentsResource
295
+
296
+ self._environments = EnvironmentsResource(self)
297
+ return self._environments
298
+
299
+ @property
300
+ def service_map_dependencies(self) -> ServiceMapDependenciesResource:
301
+ """Access the Service Map Dependencies API."""
302
+ if self._service_map_dependencies is None:
303
+ from .resources.service_map_dependencies import ServiceMapDependenciesResource
304
+
305
+ self._service_map_dependencies = ServiceMapDependenciesResource(self)
306
+ return self._service_map_dependencies
307
+
308
+ # -------------------------------------------------------------------------
309
+ # HTTP client management
310
+ # -------------------------------------------------------------------------
311
+
312
+ def _get_sync_client(self) -> httpx.Client:
313
+ """Get or create the sync HTTP client."""
314
+ if self._sync_client is None:
315
+ self._sync_client = httpx.Client(
316
+ base_url=self._base_url,
317
+ headers=self._auth.get_headers(),
318
+ timeout=self._timeout,
319
+ )
320
+ return self._sync_client
321
+
322
+ def _get_async_client(self) -> httpx.AsyncClient:
323
+ """Get or create the async HTTP client."""
324
+ if self._async_client is None:
325
+ self._async_client = httpx.AsyncClient(
326
+ base_url=self._base_url,
327
+ headers=self._auth.get_headers(),
328
+ timeout=self._timeout,
329
+ )
330
+ return self._async_client
331
+
332
+ # -------------------------------------------------------------------------
333
+ # Context managers
334
+ # -------------------------------------------------------------------------
335
+
336
+ async def __aenter__(self) -> HoneycombClient:
337
+ """Async context manager entry."""
338
+ return self
339
+
340
+ async def __aexit__(self, *args: Any) -> None:
341
+ """Async context manager exit."""
342
+ await self.aclose()
343
+
344
+ def __enter__(self) -> HoneycombClient:
345
+ """Sync context manager entry."""
346
+ if not self._sync_mode:
347
+ raise RuntimeError("Use 'async with' for async mode, or pass sync=True to constructor")
348
+ return self
349
+
350
+ def __exit__(self, *args: Any) -> None:
351
+ """Sync context manager exit."""
352
+ self.close()
353
+
354
+ async def aclose(self) -> None:
355
+ """Close async HTTP client."""
356
+ if self._async_client is not None:
357
+ await self._async_client.aclose()
358
+ self._async_client = None
359
+
360
+ def close(self) -> None:
361
+ """Close sync HTTP client."""
362
+ if self._sync_client is not None:
363
+ self._sync_client.close()
364
+ self._sync_client = None
365
+
366
+ # -------------------------------------------------------------------------
367
+ # Request methods (internal)
368
+ # -------------------------------------------------------------------------
369
+
370
+ def _parse_rate_limit_headers(self, response: httpx.Response) -> RateLimitInfo:
371
+ """Parse rate limit information from response headers.
372
+
373
+ Supports multiple header formats:
374
+ - RateLimit: limit=100, remaining=50, reset=60
375
+ - X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset
376
+ """
377
+ info = RateLimitInfo()
378
+
379
+ # Try structured RateLimit header (RFC draft)
380
+ if "RateLimit" in response.headers:
381
+ rate_limit = response.headers["RateLimit"]
382
+ for part in rate_limit.split(","):
383
+ part = part.strip()
384
+ if "=" in part:
385
+ key, value = part.split("=", 1)
386
+ key = key.strip()
387
+ try:
388
+ if key == "limit":
389
+ info.limit = int(value)
390
+ elif key == "remaining":
391
+ info.remaining = int(value)
392
+ elif key == "reset":
393
+ info.reset = int(value)
394
+ except ValueError:
395
+ pass
396
+
397
+ # Try X-RateLimit-* headers (common format)
398
+ if "X-RateLimit-Limit" in response.headers:
399
+ with suppress(ValueError):
400
+ info.limit = int(response.headers["X-RateLimit-Limit"])
401
+
402
+ if "X-RateLimit-Remaining" in response.headers:
403
+ with suppress(ValueError):
404
+ info.remaining = int(response.headers["X-RateLimit-Remaining"])
405
+
406
+ if "X-RateLimit-Reset" in response.headers:
407
+ with suppress(ValueError):
408
+ info.reset = int(response.headers["X-RateLimit-Reset"])
409
+
410
+ return info
411
+
412
+ def _parse_retry_after(self, response: httpx.Response) -> int | None:
413
+ """Parse Retry-After header.
414
+
415
+ Supports both formats:
416
+ - Delay-seconds: "60"
417
+ - HTTP-date: "Wed, 21 Oct 2015 07:28:00 GMT"
418
+
419
+ Returns:
420
+ Number of seconds to wait, or None if header not present.
421
+ """
422
+ retry_after = response.headers.get("Retry-After")
423
+ if not retry_after:
424
+ return None
425
+
426
+ # Try parsing as integer (seconds)
427
+ try:
428
+ return int(retry_after)
429
+ except ValueError:
430
+ pass
431
+
432
+ # Try parsing as HTTP date (RFC 7231)
433
+ try:
434
+ retry_date = parsedate_to_datetime(retry_after)
435
+ now = datetime.now(retry_date.tzinfo)
436
+ delta = (retry_date - now).total_seconds()
437
+ return max(int(delta), 0)
438
+ except (ValueError, TypeError):
439
+ pass
440
+
441
+ return None
442
+
443
+ def _parse_error_response(self, response: httpx.Response) -> tuple[str, list[dict] | None]:
444
+ """Parse error message from response body.
445
+
446
+ Handles multiple error formats:
447
+ - Simple: {"error": "message"}
448
+ - RFC 7807: {"title": "...", "detail": "..."}
449
+ - JSON:API: {"errors": [{"detail": "..."}]}
450
+ """
451
+ try:
452
+ body = response.json()
453
+ except Exception:
454
+ return response.text or "Unknown error", None
455
+
456
+ errors: list[dict] | None = None
457
+
458
+ # Simple format (most common for Honeycomb)
459
+ if "error" in body:
460
+ return body["error"], None
461
+
462
+ # RFC 7807 Problem Details
463
+ if "title" in body:
464
+ msg = body["title"]
465
+ if "detail" in body:
466
+ msg = f"{msg}: {body['detail']}"
467
+ errors = body.get("type_detail")
468
+ return msg, errors
469
+
470
+ # JSON:API format
471
+ if "errors" in body and isinstance(body["errors"], list):
472
+ first = body["errors"][0] if body["errors"] else {}
473
+ msg = first.get("detail") or first.get("title") or "Unknown error"
474
+ return msg, body["errors"]
475
+
476
+ return str(body), None
477
+
478
+ def _raise_for_status(self, response: httpx.Response) -> None:
479
+ """Raise appropriate exception for error responses."""
480
+ if response.is_success:
481
+ return
482
+
483
+ status = response.status_code
484
+ message, errors = self._parse_error_response(response)
485
+ request_id = response.headers.get("X-Request-Id")
486
+
487
+ if status == 401:
488
+ raise HoneycombAuthError(message, status, request_id)
489
+ elif status == 403:
490
+ raise HoneycombForbiddenError(message, status, request_id)
491
+ elif status == 404:
492
+ raise HoneycombNotFoundError(message, status, request_id)
493
+ elif status == 422:
494
+ raise HoneycombValidationError(message, status, request_id, errors=errors)
495
+ elif status == 429:
496
+ retry_after = self._parse_retry_after(response)
497
+ raise HoneycombRateLimitError(message, status, request_id, retry_after=retry_after)
498
+ elif 500 <= status < 600:
499
+ raise HoneycombServerError(message, status, request_id)
500
+ else:
501
+ raise HoneycombAPIError(message, status, request_id)
502
+
503
+ def _should_retry(self, response: httpx.Response, attempt: int) -> bool:
504
+ """Determine if request should be retried."""
505
+ if attempt >= self._retry_config.max_retries:
506
+ return False
507
+ return response.status_code in self._retry_config.retry_statuses
508
+
509
+ def _calculate_backoff(self, attempt: int, retry_after: int | None = None) -> float:
510
+ """Calculate backoff delay for retry.
511
+
512
+ Args:
513
+ attempt: The current retry attempt number (0-indexed).
514
+ retry_after: Explicit retry delay in seconds from server (optional).
515
+
516
+ Returns:
517
+ Number of seconds to wait before retrying.
518
+ """
519
+ if retry_after:
520
+ return float(retry_after)
521
+
522
+ # Exponential backoff: base_delay * (exponential_base ^ attempt)
523
+ delay = self._retry_config.base_delay * (self._retry_config.exponential_base**attempt)
524
+ return min(delay, self._retry_config.max_delay)
525
+
526
+ # -------------------------------------------------------------------------
527
+ # Async request methods
528
+ # -------------------------------------------------------------------------
529
+
530
+ async def _request_async(
531
+ self,
532
+ method: str,
533
+ path: str,
534
+ *,
535
+ json: dict | None = None,
536
+ params: dict | None = None,
537
+ headers: dict[str, str] | None = None,
538
+ ) -> httpx.Response:
539
+ """Make an async HTTP request with retry logic."""
540
+ client = self._get_async_client()
541
+ last_response: httpx.Response | None = None
542
+
543
+ for attempt in range(self._max_retries + 1):
544
+ try:
545
+ response = await client.request(
546
+ method,
547
+ path,
548
+ json=json,
549
+ params=params,
550
+ headers=headers,
551
+ )
552
+ last_response = response
553
+
554
+ if response.is_success:
555
+ return response
556
+
557
+ if self._should_retry(response, attempt):
558
+ retry_after = self._parse_retry_after(response)
559
+ delay = self._calculate_backoff(attempt, retry_after)
560
+ await asyncio.sleep(delay)
561
+ continue
562
+
563
+ # Non-retryable error
564
+ self._raise_for_status(response)
565
+
566
+ except httpx.TimeoutException as e:
567
+ if attempt < self._max_retries:
568
+ await asyncio.sleep(self._calculate_backoff(attempt))
569
+ continue
570
+ raise HoneycombTimeoutError(timeout=self._timeout) from e
571
+
572
+ except httpx.ConnectError as e:
573
+ if attempt < self._max_retries:
574
+ await asyncio.sleep(self._calculate_backoff(attempt))
575
+ continue
576
+ raise HoneycombConnectionError(original_error=e) from e
577
+
578
+ # Should not reach here, but just in case
579
+ if last_response is not None:
580
+ self._raise_for_status(last_response)
581
+ raise HoneycombAPIError("Max retries exceeded", 0)
582
+
583
+ async def get_async(self, path: str, *, params: dict | None = None) -> httpx.Response:
584
+ """Make an async GET request."""
585
+ return await self._request_async("GET", path, params=params)
586
+
587
+ async def post_async(
588
+ self,
589
+ path: str,
590
+ *,
591
+ json: dict | None = None,
592
+ params: dict | None = None,
593
+ headers: dict[str, str] | None = None,
594
+ ) -> httpx.Response:
595
+ """Make an async POST request."""
596
+ return await self._request_async("POST", path, json=json, params=params, headers=headers)
597
+
598
+ async def put_async(
599
+ self,
600
+ path: str,
601
+ *,
602
+ json: dict | None = None,
603
+ params: dict | None = None,
604
+ headers: dict[str, str] | None = None,
605
+ ) -> httpx.Response:
606
+ """Make an async PUT request."""
607
+ return await self._request_async("PUT", path, json=json, params=params, headers=headers)
608
+
609
+ async def patch_async(
610
+ self,
611
+ path: str,
612
+ *,
613
+ json: dict | None = None,
614
+ params: dict | None = None,
615
+ headers: dict[str, str] | None = None,
616
+ ) -> httpx.Response:
617
+ """Make an async PATCH request."""
618
+ return await self._request_async("PATCH", path, json=json, params=params, headers=headers)
619
+
620
+ async def delete_async(self, path: str, *, params: dict | None = None) -> httpx.Response:
621
+ """Make an async DELETE request."""
622
+ return await self._request_async("DELETE", path, params=params)
623
+
624
+ # -------------------------------------------------------------------------
625
+ # Sync request methods
626
+ # -------------------------------------------------------------------------
627
+
628
+ def _request_sync(
629
+ self,
630
+ method: str,
631
+ path: str,
632
+ *,
633
+ json: dict | None = None,
634
+ params: dict | None = None,
635
+ headers: dict[str, str] | None = None,
636
+ ) -> httpx.Response:
637
+ """Make a sync HTTP request with retry logic."""
638
+ import time
639
+
640
+ client = self._get_sync_client()
641
+ last_response: httpx.Response | None = None
642
+
643
+ for attempt in range(self._max_retries + 1):
644
+ try:
645
+ response = client.request(
646
+ method,
647
+ path,
648
+ json=json,
649
+ params=params,
650
+ headers=headers,
651
+ )
652
+ last_response = response
653
+
654
+ if response.is_success:
655
+ return response
656
+
657
+ if self._should_retry(response, attempt):
658
+ retry_after = self._parse_retry_after(response)
659
+ delay = self._calculate_backoff(attempt, retry_after)
660
+ time.sleep(delay)
661
+ continue
662
+
663
+ # Non-retryable error
664
+ self._raise_for_status(response)
665
+
666
+ except httpx.TimeoutException as e:
667
+ if attempt < self._max_retries:
668
+ time.sleep(self._calculate_backoff(attempt))
669
+ continue
670
+ raise HoneycombTimeoutError(timeout=self._timeout) from e
671
+
672
+ except httpx.ConnectError as e:
673
+ if attempt < self._max_retries:
674
+ time.sleep(self._calculate_backoff(attempt))
675
+ continue
676
+ raise HoneycombConnectionError(original_error=e) from e
677
+
678
+ # Should not reach here, but just in case
679
+ if last_response is not None:
680
+ self._raise_for_status(last_response)
681
+ raise HoneycombAPIError("Max retries exceeded", 0)
682
+
683
+ def get_sync(self, path: str, *, params: dict | None = None) -> httpx.Response:
684
+ """Make a sync GET request."""
685
+ return self._request_sync("GET", path, params=params)
686
+
687
+ def post_sync(
688
+ self,
689
+ path: str,
690
+ *,
691
+ json: dict | None = None,
692
+ params: dict | None = None,
693
+ headers: dict[str, str] | None = None,
694
+ ) -> httpx.Response:
695
+ """Make a sync POST request."""
696
+ return self._request_sync("POST", path, json=json, params=params, headers=headers)
697
+
698
+ def put_sync(
699
+ self,
700
+ path: str,
701
+ *,
702
+ json: dict | None = None,
703
+ params: dict | None = None,
704
+ headers: dict[str, str] | None = None,
705
+ ) -> httpx.Response:
706
+ """Make a sync PUT request."""
707
+ return self._request_sync("PUT", path, json=json, params=params, headers=headers)
708
+
709
+ def patch_sync(
710
+ self,
711
+ path: str,
712
+ *,
713
+ json: dict | None = None,
714
+ params: dict | None = None,
715
+ headers: dict[str, str] | None = None,
716
+ ) -> httpx.Response:
717
+ """Make a sync PATCH request."""
718
+ return self._request_sync("PATCH", path, json=json, params=params, headers=headers)
719
+
720
+ def delete_sync(self, path: str, *, params: dict | None = None) -> httpx.Response:
721
+ """Make a sync DELETE request."""
722
+ return self._request_sync("DELETE", path, params=params)
723
+
724
+ # -------------------------------------------------------------------------
725
+ # Convenience properties
726
+ # -------------------------------------------------------------------------
727
+
728
+ @property
729
+ def is_sync(self) -> bool:
730
+ """Return True if client is in sync mode."""
731
+ return self._sync_mode
732
+
733
+ @property
734
+ def base_url(self) -> str:
735
+ """Return the API base URL."""
736
+ return self._base_url