tinybird 0.0.1.dev311__tar.gz → 0.0.1.dev312__tar.gz

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 (152) hide show
  1. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/PKG-INFO +1 -1
  2. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/__cli__.py +2 -2
  3. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/local.py +72 -18
  4. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/local_common.py +275 -153
  5. tinybird-0.0.1.dev312/tinybird/tb/modules/local_logs.py +196 -0
  6. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird.egg-info/PKG-INFO +1 -1
  7. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird.egg-info/SOURCES.txt +1 -0
  8. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/setup.cfg +0 -0
  9. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/__cli__.py +0 -0
  10. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/ch_utils/constants.py +0 -0
  11. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/ch_utils/engine.py +0 -0
  12. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/check_pypi.py +0 -0
  13. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/client.py +0 -0
  14. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/config.py +0 -0
  15. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/connectors.py +0 -0
  16. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/context.py +0 -0
  17. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/datafile/common.py +0 -0
  18. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/datafile/exceptions.py +0 -0
  19. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/datafile/parse_connection.py +0 -0
  20. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/datafile/parse_datasource.py +0 -0
  21. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/datafile/parse_pipe.py +0 -0
  22. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/datatypes.py +0 -0
  23. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/feedback_manager.py +0 -0
  24. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/git_settings.py +0 -0
  25. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/prompts.py +0 -0
  26. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/service_datasources.py +0 -0
  27. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/sql.py +0 -0
  28. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/sql_template.py +0 -0
  29. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/sql_template_fmt.py +0 -0
  30. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/sql_toolset.py +0 -0
  31. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/syncasync.py +0 -0
  32. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/check_pypi.py +0 -0
  33. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/cli.py +0 -0
  34. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/client.py +0 -0
  35. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/config.py +0 -0
  36. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/agent/__init__.py +0 -0
  37. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/agent/agent.py +0 -0
  38. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/agent/animations.py +0 -0
  39. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/agent/banner.py +0 -0
  40. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/agent/command_agent.py +0 -0
  41. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/agent/compactor.py +0 -0
  42. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/agent/explore_agent.py +0 -0
  43. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/agent/file_agent.py +0 -0
  44. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/agent/memory.py +0 -0
  45. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/agent/mock_agent.py +0 -0
  46. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/agent/models.py +0 -0
  47. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/agent/prompts.py +0 -0
  48. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/agent/testing_agent.py +0 -0
  49. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/agent/tools/__init__.py +0 -0
  50. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/agent/tools/analyze.py +0 -0
  51. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/agent/tools/append.py +0 -0
  52. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/agent/tools/build.py +0 -0
  53. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/agent/tools/datafile.py +0 -0
  54. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/agent/tools/deploy.py +0 -0
  55. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/agent/tools/deploy_check.py +0 -0
  56. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/agent/tools/diff_resource.py +0 -0
  57. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/agent/tools/execute_query.py +0 -0
  58. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/agent/tools/file.py +0 -0
  59. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/agent/tools/get_endpoint_stats.py +0 -0
  60. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/agent/tools/get_openapi_definition.py +0 -0
  61. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/agent/tools/mock.py +0 -0
  62. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/agent/tools/plan.py +0 -0
  63. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/agent/tools/request_endpoint.py +0 -0
  64. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/agent/tools/run_command.py +0 -0
  65. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/agent/tools/secret.py +0 -0
  66. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/agent/tools/test.py +0 -0
  67. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/agent/utils.py +0 -0
  68. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/build.py +0 -0
  69. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/build_common.py +0 -0
  70. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/cicd.py +0 -0
  71. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/cli.py +0 -0
  72. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/common.py +0 -0
  73. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/config.py +0 -0
  74. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/connection.py +0 -0
  75. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/copy.py +0 -0
  76. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/create.py +0 -0
  77. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/datafile/build.py +0 -0
  78. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/datafile/build_common.py +0 -0
  79. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/datafile/build_datasource.py +0 -0
  80. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/datafile/build_pipe.py +0 -0
  81. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/datafile/diff.py +0 -0
  82. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/datafile/fixture.py +0 -0
  83. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/datafile/format_common.py +0 -0
  84. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/datafile/format_datasource.py +0 -0
  85. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/datafile/format_pipe.py +0 -0
  86. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/datafile/pipe_checker.py +0 -0
  87. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/datafile/playground.py +0 -0
  88. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/datafile/pull.py +0 -0
  89. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/datasource.py +0 -0
  90. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/deployment.py +0 -0
  91. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/deployment_common.py +0 -0
  92. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/deprecations.py +0 -0
  93. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/dev_server.py +0 -0
  94. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/endpoint.py +0 -0
  95. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/environment.py +0 -0
  96. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/exceptions.py +0 -0
  97. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/feedback_manager.py +0 -0
  98. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/info.py +0 -0
  99. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/infra.py +0 -0
  100. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/job.py +0 -0
  101. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/llm.py +0 -0
  102. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/llm_utils.py +0 -0
  103. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/login.py +0 -0
  104. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/login_common.py +0 -0
  105. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/logout.py +0 -0
  106. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/materialization.py +0 -0
  107. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/mock.py +0 -0
  108. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/mock_common.py +0 -0
  109. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/open.py +0 -0
  110. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/pipe.py +0 -0
  111. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/project.py +0 -0
  112. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/regions.py +0 -0
  113. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/secret.py +0 -0
  114. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/secret_common.py +0 -0
  115. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/shell.py +0 -0
  116. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/sink.py +0 -0
  117. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/table.py +0 -0
  118. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/telemetry.py +0 -0
  119. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/test.py +0 -0
  120. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/test_common.py +0 -0
  121. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/tinyunit/tinyunit.py +0 -0
  122. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/tinyunit/tinyunit_lib.py +0 -0
  123. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/token.py +0 -0
  124. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/watch.py +0 -0
  125. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/workspace.py +0 -0
  126. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb/modules/workspace_members.py +0 -0
  127. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb_cli.py +0 -0
  128. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb_cli_modules/auth.py +0 -0
  129. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb_cli_modules/branch.py +0 -0
  130. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb_cli_modules/cicd.py +0 -0
  131. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb_cli_modules/cli.py +0 -0
  132. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb_cli_modules/common.py +0 -0
  133. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb_cli_modules/config.py +0 -0
  134. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb_cli_modules/connection.py +0 -0
  135. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb_cli_modules/datasource.py +0 -0
  136. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb_cli_modules/exceptions.py +0 -0
  137. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb_cli_modules/fmt.py +0 -0
  138. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb_cli_modules/job.py +0 -0
  139. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb_cli_modules/pipe.py +0 -0
  140. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb_cli_modules/regions.py +0 -0
  141. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb_cli_modules/tag.py +0 -0
  142. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb_cli_modules/telemetry.py +0 -0
  143. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb_cli_modules/test.py +0 -0
  144. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb_cli_modules/tinyunit/tinyunit.py +0 -0
  145. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb_cli_modules/tinyunit/tinyunit_lib.py +0 -0
  146. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb_cli_modules/workspace.py +0 -0
  147. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tb_cli_modules/workspace_members.py +0 -0
  148. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird/tornado_template.py +0 -0
  149. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird.egg-info/dependency_links.txt +0 -0
  150. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird.egg-info/entry_points.txt +0 -0
  151. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird.egg-info/requires.txt +0 -0
  152. {tinybird-0.0.1.dev311 → tinybird-0.0.1.dev312}/tinybird.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: tinybird
3
- Version: 0.0.1.dev311
3
+ Version: 0.0.1.dev312
4
4
  Summary: Tinybird Command Line Tool
5
5
  Home-page: https://www.tinybird.co/docs/forward/commands
6
6
  Author: Tinybird
@@ -4,5 +4,5 @@ __description__ = 'Tinybird Command Line Tool'
4
4
  __url__ = 'https://www.tinybird.co/docs/forward/commands'
5
5
  __author__ = 'Tinybird'
6
6
  __author_email__ = 'support@tinybird.co'
7
- __version__ = '0.0.1.dev311'
8
- __revision__ = 'd56057f'
7
+ __version__ = '0.0.1.dev312'
8
+ __revision__ = '2324ba4'
@@ -10,7 +10,9 @@ from docker.client import DockerClient
10
10
 
11
11
  from tinybird.tb.modules.cli import cli
12
12
  from tinybird.tb.modules.common import echo_json, update_cli
13
+ from tinybird.tb.modules.exceptions import CLILocalException
13
14
  from tinybird.tb.modules.feedback_manager import FeedbackManager
15
+ from tinybird.tb.modules.info import get_local_info
14
16
  from tinybird.tb.modules.local_common import (
15
17
  TB_CONTAINER_NAME,
16
18
  TB_LOCAL_ADDRESS,
@@ -18,6 +20,19 @@ from tinybird.tb.modules.local_common import (
18
20
  get_existing_container_with_matching_env,
19
21
  start_tinybird_local,
20
22
  )
23
+ from tinybird.tb.modules.local_logs import (
24
+ check_memory_sufficient,
25
+ clickhouse_is_ready,
26
+ container_is_ready,
27
+ container_is_starting,
28
+ container_is_stopping,
29
+ container_is_unhealthy,
30
+ container_stats,
31
+ events_is_ready,
32
+ local_authentication_is_ready,
33
+ redis_is_ready,
34
+ server_is_ready,
35
+ )
21
36
 
22
37
 
23
38
  def stop_tinybird_local(docker_client: DockerClient) -> None:
@@ -76,30 +91,69 @@ def stop() -> None:
76
91
  @click.pass_context
77
92
  def status(ctx: click.Context) -> None:
78
93
  """Check status of Tinybird Local"""
94
+
95
+ click.echo(FeedbackManager.highlight(message="» Checking status..."))
79
96
  docker_client = get_docker_client()
80
97
  container = get_existing_container_with_matching_env(docker_client, TB_CONTAINER_NAME, {})
81
98
 
82
- if container:
83
- status = container.status
84
- health = container.attrs.get("State", {}).get("Health", {}).get("Status")
85
-
86
- if status == "running" and health == "healthy":
87
- click.echo(FeedbackManager.success(message="✓ Tinybird Local is ready!"))
88
- click.echo(FeedbackManager.highlight(message="\n» Tinybird Local:"))
89
- from tinybird.tb.modules.info import get_local_info
90
-
91
- config = ctx.ensure_object(dict).get("config", {})
92
- get_local_info(config)
93
- elif status == "restarting" or (status == "running" and health == "starting"):
94
- click.echo(FeedbackManager.highlight(message="* Tinybird Local is starting..."))
95
- elif status == "removing":
96
- click.echo(FeedbackManager.highlight(message="* Tinybird Local is stopping..."))
99
+ try:
100
+ if container:
101
+ if container_is_ready(container):
102
+ stats = container_stats(container, docker_client)
103
+ click.echo(FeedbackManager.info(message=f" Tinybird Local container ({stats})"))
104
+
105
+ # Check memory sufficiency
106
+ is_sufficient, warning_msg = check_memory_sufficient(container, docker_client)
107
+ if not is_sufficient and warning_msg:
108
+ click.echo(FeedbackManager.warning(message=f" {warning_msg}"))
109
+
110
+ if not clickhouse_is_ready(container):
111
+ raise Exception("Clickhouse is not ready.")
112
+ click.echo(FeedbackManager.info(message="✓ Clickhouse"))
113
+
114
+ if not redis_is_ready(container):
115
+ raise Exception("Redis is not ready.")
116
+ click.echo(FeedbackManager.info(message="✓ Redis"))
117
+
118
+ if not server_is_ready(container):
119
+ raise Exception("Server is not ready.")
120
+ click.echo(FeedbackManager.info(message="✓ Server"))
121
+
122
+ if not events_is_ready(container):
123
+ raise Exception("Events is not ready.")
124
+ click.echo(FeedbackManager.info(message="✓ Events"))
125
+
126
+ if not local_authentication_is_ready(container):
127
+ raise Exception("Tinybird Local authentication is not ready.")
128
+ click.echo(FeedbackManager.info(message="✓ Tinybird Local authentication"))
129
+
130
+ click.echo(FeedbackManager.success(message="✓ Tinybird Local is ready!"))
131
+ click.echo(FeedbackManager.highlight(message="\n» Tinybird Local:"))
132
+ config = ctx.ensure_object(dict).get("config", {})
133
+ get_local_info(config)
134
+ elif container_is_starting(container):
135
+ click.echo(FeedbackManager.highlight(message="* Tinybird Local is starting..."))
136
+ elif container_is_stopping(container):
137
+ click.echo(FeedbackManager.highlight(message="* Tinybird Local is stopping..."))
138
+ elif container_is_unhealthy(container):
139
+ is_sufficient, warning_msg = check_memory_sufficient(container, docker_client)
140
+ if not is_sufficient and warning_msg:
141
+ click.echo(FeedbackManager.warning(message=f"△ {warning_msg}"))
142
+ click.echo(
143
+ FeedbackManager.error(
144
+ message="* Tinybird Local is unhealthy. Try running `tb local restart` in a few seconds."
145
+ )
146
+ )
147
+ else:
148
+ click.echo(
149
+ FeedbackManager.error(message="✗ Tinybird Local is not running. Run 'tb local start' to start it")
150
+ )
97
151
  else:
98
152
  click.echo(
99
- FeedbackManager.info(message="✗ Tinybird Local is not running. Run 'tb local start' to start it")
153
+ FeedbackManager.error(message="✗ Tinybird Local is not running. Run 'tb local start' to start it")
100
154
  )
101
- else:
102
- click.echo(FeedbackManager.info(message="Tinybird Local is not running. Run 'tb local start' to start it"))
155
+ except Exception as e:
156
+ raise CLILocalException(FeedbackManager.error(message=f"Tinybird Local is not ready. Reason: {e}"))
103
157
 
104
158
 
105
159
  @local.command()
@@ -20,6 +20,15 @@ from tinybird.tb.client import AuthNoTokenException, TinyB
20
20
  from tinybird.tb.modules.config import CLIConfig
21
21
  from tinybird.tb.modules.exceptions import CLILocalException
22
22
  from tinybird.tb.modules.feedback_manager import FeedbackManager
23
+ from tinybird.tb.modules.local_logs import (
24
+ check_memory_sufficient,
25
+ clickhouse_is_ready,
26
+ container_stats,
27
+ events_is_ready,
28
+ local_authentication_is_ready,
29
+ redis_is_ready,
30
+ server_is_ready,
31
+ )
23
32
  from tinybird.tb.modules.secret_common import load_secrets
24
33
  from tinybird.tb.modules.telemetry import add_telemetry_event
25
34
 
@@ -228,7 +237,7 @@ def get_local_tokens() -> Dict[str, str]:
228
237
  default=True,
229
238
  )
230
239
  if yes:
231
- click.echo(FeedbackManager.highlight(message="» Starting Tinybird Local..."))
240
+ click.echo(FeedbackManager.highlight(message="» Watching Tinybird Local... (Press Ctrl+C to stop)"))
232
241
  docker_client = get_docker_client()
233
242
  start_tinybird_local(docker_client, False)
234
243
  click.echo(FeedbackManager.success(message="✓ Tinybird Local is ready!"))
@@ -314,164 +323,84 @@ def start_tinybird_local(
314
323
  # Stream logs in a separate thread while monitoring container health
315
324
  container_ready = threading.Event()
316
325
  stop_requested = threading.Event()
317
- health_check_error = {"message": ""} # Mutable dict to store error message
326
+ health_check: dict[str, str] = {}
318
327
 
319
- def check_endpoints_health() -> None:
320
- """Continuously check /tokens and /v0/health endpoints"""
321
- # Wait for container to be ready before starting health checks
322
- container_ready.wait()
323
-
324
- # Give container a moment to fully start up
325
- time.sleep(2)
326
-
327
- check_interval = 10 # Check every 10 seconds
328
-
329
- while not stop_requested.is_set():
330
- try:
331
- # Check /tokens endpoint
332
- tokens_response = requests.get(f"{TB_LOCAL_ADDRESS}/tokens", timeout=5)
333
- if tokens_response.status_code != 200:
334
- health_check_error["message"] = (
335
- f"/tokens endpoint returned status {tokens_response.status_code}. "
336
- "Tinybird Local may be unhealthy."
337
- )
338
- stop_requested.set()
339
- break
340
-
341
- # Check /v0/health endpoint
342
- health_response = requests.get(f"{TB_LOCAL_ADDRESS}/v0/health", timeout=5)
343
- if health_response.status_code != 200:
344
- health_check_error["message"] = (
345
- f"/v0/health endpoint returned status {health_response.status_code}. "
346
- "Tinybird Local may be unhealthy."
347
- )
348
- stop_requested.set()
349
- break
350
-
351
- # Verify tokens response has expected structure
352
- try:
353
- tokens_data = tokens_response.json()
354
- if not all(
355
- key in tokens_data for key in ["user_token", "admin_token", "workspace_admin_token"]
356
- ):
357
- health_check_error["message"] = (
358
- "/tokens endpoint returned unexpected data. Tinybird Local may be unhealthy."
359
- )
360
- stop_requested.set()
361
- break
362
- except json.JSONDecodeError:
363
- health_check_error["message"] = (
364
- "/tokens endpoint returned invalid JSON. Tinybird Local may be unhealthy."
365
- )
366
- stop_requested.set()
367
- break
368
-
369
- except Exception as e:
370
- # Check if it's a connection error
371
- error_str = str(e)
372
- if "connect" in error_str.lower() or "timeout" in error_str.lower():
373
- health_check_error["message"] = f"Failed to connect to Tinybird Local: {error_str}"
374
- else:
375
- health_check_error["message"] = f"Health check failed: {error_str}"
376
- stop_requested.set()
377
- break
378
-
379
- # Wait before next check
380
- for _ in range(check_interval):
381
- if stop_requested.is_set():
382
- break
383
- time.sleep(1)
384
-
385
- def stream_logs_with_health_check() -> None:
386
- """Stream logs and monitor container health in parallel"""
387
- log_names = {
388
- "/var/log/tinybird-local-setup.log": "SETUP",
389
- "/var/log/tinybird-local-server.log": "SERVER",
390
- }
391
-
392
- # Wait briefly for log files to be created
393
- retry_count = 0
394
- max_retries = 3
395
- exec_result = None
396
-
397
- while retry_count < max_retries and not stop_requested.is_set():
398
- try:
399
- # Try to tail the log files (only new logs, not historical)
400
- # Use -F to follow by name and retry if files don't exist yet
401
- cmd = ["tail", "-n", "0", "-F", *log_names.keys()]
402
- exec_result = container.exec_run(cmd=cmd, stream=True, tty=False, stdout=True, stderr=True)
403
- break # Success, exit retry loop
404
- except Exception:
405
- # Log file might not exist yet, wait and retry
406
- retry_count += 1
407
- if retry_count < max_retries:
408
- time.sleep(2)
409
-
410
- # If we couldn't start tailing, fall back to container logs
411
- if not exec_result and not stop_requested.is_set():
412
- try:
413
- for line in container.logs(stream=True, follow=True):
414
- if stop_requested.is_set():
415
- break
416
- click.echo(line.decode("utf-8").rstrip())
417
- return
418
- except Exception:
419
- return # Silently ignore errors in log streaming
420
-
421
- # Stream logs continuously
422
- if exec_result:
423
- try:
424
- for line in exec_result.output:
425
- if stop_requested.is_set():
426
- break
427
-
428
- decoded_line = line.decode("utf-8").rstrip()
429
-
430
- # Skip tail error messages about files not existing yet
431
- if "tail:" in decoded_line and (
432
- "cannot open" in decoded_line or "no files remaining" in decoded_line
433
- ):
434
- continue
435
-
436
- # Replace file path headers with friendly names
437
- for file_path, friendly_name in log_names.items():
438
- log_header = f"==> {file_path} <=="
439
- if log_header in decoded_line:
440
- decoded_line = decoded_line.replace(log_header, f"==> {friendly_name} <==")
441
-
442
- # Print "ready" message when container becomes healthy
443
- if container_ready.is_set() and not hasattr(stream_logs_with_health_check, "ready_printed"):
444
- click.echo(FeedbackManager.success(message="✓ Tinybird Local is ready!"))
445
- click.echo(
446
- FeedbackManager.highlight(message="» Watching Tinybird Local... (Press Ctrl+C to stop)")
447
- )
448
- stream_logs_with_health_check.ready_printed = True # type: ignore
449
-
450
- click.echo(decoded_line)
451
- except Exception:
452
- pass # Silently ignore errors when stream is interrupted
453
-
454
- log_thread = threading.Thread(target=stream_logs_with_health_check, daemon=True)
328
+ log_thread = threading.Thread(
329
+ target=stream_logs_with_health_check,
330
+ args=(container, container_ready, stop_requested),
331
+ daemon=True,
332
+ )
455
333
  log_thread.start()
456
334
 
457
- health_check_thread = threading.Thread(target=check_endpoints_health, daemon=True)
335
+ health_check_thread = threading.Thread(
336
+ target=check_endpoints_health,
337
+ args=(container, docker_client, container_ready, stop_requested, health_check),
338
+ daemon=True,
339
+ )
458
340
  health_check_thread.start()
459
341
 
460
342
  # Monitor container health in main thread
343
+ memory_warning_shown = False
461
344
  try:
462
345
  while True:
463
346
  container.reload() # Refresh container attributes
464
347
  health = container.attrs.get("State", {}).get("Health", {}).get("Status")
348
+ if not container_ready.is_set():
349
+ click.echo(FeedbackManager.info(message=f"* Tinybird Local container status: {health}"))
350
+ stats = container_stats(container, docker_client)
351
+ click.echo(f"* {stats}")
352
+
353
+ # Check memory sufficiency
354
+ if not memory_warning_shown:
355
+ is_sufficient, warning_msg = check_memory_sufficient(container, docker_client)
356
+ if not is_sufficient and warning_msg:
357
+ click.echo(FeedbackManager.warning(message=f"△ {warning_msg}"))
358
+ raise CLILocalException(
359
+ FeedbackManager.error(
360
+ message="Tinybird Local is unhealthy. Adjust memory and try again."
361
+ )
362
+ )
363
+
465
364
  if health == "healthy":
365
+ click.echo(FeedbackManager.highlight(message="» Checking services..."))
366
+ stats = container_stats(container, docker_client)
367
+ click.echo(FeedbackManager.info(message=f"✓ Tinybird Local container ({stats})"))
368
+
369
+ # Check memory sufficiency before checking services
370
+ if not memory_warning_shown:
371
+ is_sufficient, warning_msg = check_memory_sufficient(container, docker_client)
372
+ if not is_sufficient and warning_msg:
373
+ click.echo(FeedbackManager.warning(message=f"△ {warning_msg}"))
374
+ memory_warning_shown = True
375
+
376
+ if not clickhouse_is_ready(container):
377
+ raise Exception("Clickhouse is not ready.")
378
+ click.echo(FeedbackManager.info(message="✓ Clickhouse"))
379
+
380
+ if not redis_is_ready(container):
381
+ raise Exception("Redis is not ready.")
382
+ click.echo(FeedbackManager.info(message="✓ Redis"))
383
+
384
+ if not server_is_ready(container):
385
+ raise Exception("Server is not ready.")
386
+ click.echo(FeedbackManager.info(message="✓ Server"))
387
+
388
+ if not events_is_ready(container):
389
+ raise Exception("Events is not ready.")
390
+ click.echo(FeedbackManager.info(message="✓ Events"))
391
+
392
+ if not local_authentication_is_ready(container):
393
+ raise Exception("Tinybird Local authentication is not ready.")
394
+ click.echo(FeedbackManager.info(message="✓ Tinybird Local authentication"))
466
395
  container_ready.set()
467
396
  # Keep monitoring and streaming logs until Ctrl+C or health check failure
468
397
  while True:
469
398
  # Check if health check detected an error
470
- if stop_requested.is_set() and health_check_error["message"]:
399
+ if stop_requested.is_set() and health_check.get("error"):
471
400
  time.sleep(0.5) # Give log thread time to finish printing
472
- click.echo(
401
+ raise CLILocalException(
473
402
  FeedbackManager.error(
474
- message=f"\n✗ {health_check_error['message']}\n"
403
+ message=f"{health_check.get('error')}\n"
475
404
  "Please run `tb local restart` to restart the container."
476
405
  )
477
406
  )
@@ -479,31 +408,70 @@ def start_tinybird_local(
479
408
  time.sleep(1)
480
409
  if health == "unhealthy":
481
410
  stop_requested.set()
482
- raise CLILocalException(
483
- FeedbackManager.error(
484
- message="Tinybird Local is unhealthy. Try running `tb local restart` in a few seconds."
411
+ # Check if memory might be the cause of unhealthy status
412
+ is_sufficient, warning_msg = check_memory_sufficient(container, docker_client)
413
+ error_msg = "Tinybird Local is unhealthy. Try running `tb local restart` in a few seconds."
414
+ if not is_sufficient and warning_msg:
415
+ error_msg = (
416
+ "Tinybird Local is unhealthy.\nnAfter adjusting memory, try running `tb local restart`."
485
417
  )
486
- )
418
+ raise CLILocalException(FeedbackManager.error(message=error_msg))
487
419
  time.sleep(5)
488
420
  except KeyboardInterrupt:
489
421
  stop_requested.set()
490
422
  click.echo(FeedbackManager.highlight(message="» Stopping Tinybird Local..."))
491
- container.stop()
492
- click.echo(FeedbackManager.success(message="✓ Tinybird Local stopped."))
423
+ try:
424
+ container.stop()
425
+ click.echo(FeedbackManager.success(message="✓ Tinybird Local stopped."))
426
+ except KeyboardInterrupt:
427
+ click.echo(FeedbackManager.warning(message="⚠ Forced exit. Container may still be running."))
428
+ click.echo(FeedbackManager.info(message=" Run `tb local stop` to stop the container manually."))
493
429
  return
494
430
 
495
431
  # Non-watch mode: just wait for container to be healthy
432
+ memory_warning_shown = False
496
433
  while True:
497
434
  container.reload() # Refresh container attributes
498
435
  health = container.attrs.get("State", {}).get("Health", {}).get("Status")
436
+ click.echo(FeedbackManager.info(message=f"* Tinybird Local container status: {health}"))
437
+ stats = container_stats(container, docker_client)
438
+ click.echo(f"* {stats}")
439
+
440
+ # Check memory sufficiency
441
+ if not memory_warning_shown:
442
+ is_sufficient, warning_msg = check_memory_sufficient(container, docker_client)
443
+ if not is_sufficient and warning_msg:
444
+ click.echo(FeedbackManager.warning(message=f"△ {warning_msg}"))
445
+ memory_warning_shown = True
446
+ raise CLILocalException(
447
+ FeedbackManager.error(message="Tinybird Local is unhealthy. Adjust memory and try again.")
448
+ )
449
+
499
450
  if health == "healthy":
451
+ click.echo(FeedbackManager.highlight(message="» Checking services..."))
452
+ stats = container_stats(container, docker_client)
453
+ click.echo(FeedbackManager.info(message=f"✓ Tinybird Local container ({stats})"))
454
+ if not clickhouse_is_ready(container):
455
+ raise Exception("Clickhouse is not ready.")
456
+ click.echo(FeedbackManager.info(message="✓ Clickhouse"))
457
+ if not redis_is_ready(container):
458
+ raise Exception("Redis is not ready.")
459
+ click.echo(FeedbackManager.info(message="✓ Redis"))
460
+ if not server_is_ready(container):
461
+ raise Exception("Server is not ready.")
462
+ click.echo(FeedbackManager.info(message="✓ Server"))
463
+ if not events_is_ready(container):
464
+ raise Exception("Events is not ready.")
465
+ click.echo(FeedbackManager.info(message="✓ Events"))
466
+ if not local_authentication_is_ready(container):
467
+ raise Exception("Tinybird Local authentication is not ready.")
468
+ click.echo(FeedbackManager.info(message="✓ Tinybird Local authentication"))
500
469
  break
501
470
  if health == "unhealthy":
502
- raise CLILocalException(
503
- FeedbackManager.error(
504
- message="Tinybird Local is unhealthy. Try running `tb local restart` in a few seconds."
505
- )
506
- )
471
+ # Check if memory might be the cause of unhealthy status
472
+ is_sufficient, warning_msg = check_memory_sufficient(container, docker_client)
473
+ error_msg = "Tinybird Local is unhealthy. Try running `tb local restart` in a few seconds."
474
+ raise CLILocalException(FeedbackManager.error(message=error_msg))
507
475
  time.sleep(5)
508
476
 
509
477
  # Remove tinybird-local dangling images to avoid running out of disk space
@@ -667,3 +635,157 @@ def get_use_aws_creds() -> dict[str, str]:
667
635
  )
668
636
 
669
637
  return credentials
638
+
639
+
640
+ SERVICE_COLORS = {
641
+ "[EVENTS]": "\033[95m", # Magenta
642
+ "[SERVER]": "\033[94m", # Blue
643
+ "[HEALTH]": "\033[96m", # Cyan
644
+ "[KAFKA]": "\033[93m", # Yellow
645
+ "[AUTH]": "\033[90m", # Gray
646
+ }
647
+
648
+ RESET = "\033[0m"
649
+
650
+
651
+ def check_endpoints_health(
652
+ container: Container,
653
+ docker_client: DockerClient,
654
+ container_ready: threading.Event,
655
+ stop_requested: threading.Event,
656
+ health_check: dict[str, str],
657
+ ) -> None:
658
+ """Continuously check /tokens and /v0/health endpoints"""
659
+ # Wait for container to be ready before starting health checks
660
+ container_ready.wait()
661
+
662
+ # Give container a moment to fully start up
663
+ time.sleep(2)
664
+
665
+ check_interval = 10 # Check every 10 seconds
666
+
667
+ while not stop_requested.is_set():
668
+ try:
669
+ # Check /tokens endpoint
670
+ tokens_response = requests.get(f"{TB_LOCAL_ADDRESS}/tokens", timeout=5)
671
+ if tokens_response.status_code != 200:
672
+ health_check["error"] = (
673
+ f"/tokens endpoint returned status {tokens_response.status_code}. Tinybird Local may be unhealthy."
674
+ )
675
+ stop_requested.set()
676
+ break
677
+
678
+ # Check /v0/health endpoint
679
+ health_response = requests.get(f"{TB_LOCAL_ADDRESS}/v0/health", timeout=5)
680
+ if health_response.status_code != 200:
681
+ health_check["error"] = (
682
+ f"/v0/health endpoint returned status {health_response.status_code}. "
683
+ "Tinybird Local may be unhealthy."
684
+ )
685
+ stop_requested.set()
686
+ break
687
+
688
+ # Verify tokens response has expected structure
689
+ try:
690
+ tokens_data = tokens_response.json()
691
+ if not all(key in tokens_data for key in ["user_token", "admin_token", "workspace_admin_token"]):
692
+ health_check["error"] = (
693
+ "/tokens endpoint returned unexpected data. Tinybird Local may be unhealthy."
694
+ )
695
+ stop_requested.set()
696
+ break
697
+ except json.JSONDecodeError:
698
+ health_check["error"] = "/tokens endpoint returned invalid JSON. Tinybird Local may be unhealthy."
699
+ stop_requested.set()
700
+ break
701
+
702
+ except Exception as e:
703
+ # Check if it's a connection error
704
+ error_str = str(e)
705
+ if "connect" in error_str.lower() or "timeout" in error_str.lower():
706
+ health_check["error"] = f"Failed to connect to Tinybird Local: {error_str}"
707
+ else:
708
+ health_check["error"] = f"Health check failed: {error_str}"
709
+ stop_requested.set()
710
+ break
711
+
712
+ if container_ready.is_set():
713
+ stats = container_stats(container, docker_client)
714
+ click.echo(f"{SERVICE_COLORS['[HEALTH]']}[HEALTH]{RESET} {stats}")
715
+
716
+ # Wait before next check
717
+ for _ in range(check_interval):
718
+ if stop_requested.is_set():
719
+ break
720
+ time.sleep(1)
721
+
722
+
723
+ def stream_logs_with_health_check(
724
+ container: Container, container_ready: threading.Event, stop_requested: threading.Event
725
+ ) -> None:
726
+ """Stream logs and monitor container health in parallel"""
727
+ # Wait for container to be ready before starting health checks
728
+ container_ready.wait()
729
+
730
+ # Give container a moment to fully start up
731
+ time.sleep(2)
732
+
733
+ retry_count = 0
734
+ max_retries = 10
735
+ exec_result = None
736
+
737
+ while retry_count < max_retries and not stop_requested.is_set():
738
+ try:
739
+ # Try to tail the log files (only new logs, not historical)
740
+ # Use -F to follow by name and retry if files don't exist yet
741
+ log_files = {
742
+ "/var/log/tinybird-local-server.log": "SERVER",
743
+ "/var/log/tinybird-local-hfi.log": "EVENTS",
744
+ "/var/log/tinybird-local-setup.log": "AUTH",
745
+ "/var/log/tinybird-local-kafka.log": "KAFKA",
746
+ }
747
+ # Build commands to tail each file and prefix with its label (using stdbuf for unbuffered output)
748
+ tail_commands = [
749
+ f'tail -n 0 -f {path} | stdbuf -oL sed "s/^/[{source}] /"' for path, source in log_files.items()
750
+ ]
751
+ # Join with & to run in parallel, then wait for all
752
+ cmd = f"sh -c '({' & '.join(tail_commands)}) & wait'"
753
+ exec_result = container.exec_run(cmd, stream=True, tty=False, stdout=True, stderr=True)
754
+ break # Success, exit retry loop
755
+ except Exception:
756
+ # Log file might not exist yet, wait and retry
757
+ retry_count += 1
758
+ if retry_count < max_retries:
759
+ time.sleep(2)
760
+
761
+ # Stream logs continuously
762
+ if exec_result:
763
+ try:
764
+ for line in exec_result.output:
765
+ if stop_requested.is_set():
766
+ break
767
+
768
+ raw_line = line.decode("utf-8").rstrip()
769
+ lines = raw_line.split("\n")
770
+
771
+ # Print "ready" message when container becomes healthy
772
+ if container_ready.is_set() and not hasattr(stream_logs_with_health_check, "ready_printed"):
773
+ click.echo(FeedbackManager.success(message="✓ Tinybird Local is ready!"))
774
+ stream_logs_with_health_check.ready_printed = True # type: ignore
775
+
776
+ for line in lines:
777
+ # Apply color to service label
778
+ for service, color in SERVICE_COLORS.items():
779
+ if line.startswith(service):
780
+ message = line[len(service) :]
781
+ # extract content of message="...""
782
+ match = re.search(r'message="([^"]*)"', message)
783
+ if match:
784
+ message = match.group(1)
785
+ line = f"{color}{service}{RESET} {message}"
786
+ break
787
+
788
+ click.echo(line)
789
+
790
+ except Exception:
791
+ pass # Silently ignore errors when stream is interrupted