├── .dockerignore
├── .github
├── actions
│ └── publish_charts
│ │ └── action.yaml
└── workflows
│ └── release.yaml
├── .gitignore
├── .pre-commit-config.yaml
├── .redocly.lint-ignore.yaml
├── .redocly.yaml
├── CONTRIBUTING.md
├── CONTRIBUTORS.md
├── LICENSE
├── NOTICE
├── README.md
├── agent_api
├── __init__.py
├── app.py
├── config
│ ├── __init__.py
│ ├── cloud.py
│ ├── defaults.py
│ ├── local.py
│ ├── minikube.py
│ └── test.py
├── endpoints
│ ├── __init__.py
│ └── v1
│ │ ├── __init__.py
│ │ └── heartbeat.py
├── helpers
│ ├── __init__.py
│ └── health.py
├── routes
│ ├── __init__.py
│ └── v1_routes.py
├── schemas
│ ├── __init__.py
│ └── heartbeat.py
└── tests
│ ├── __init__.py
│ └── integration
│ ├── __init__.py
│ └── v1_endpoints
│ ├── __init__.py
│ ├── conftest.py
│ └── test_heartbeat.py
├── benchmark
├── README.md
├── cached_property.py
└── requirements.txt
├── cli
├── README.md
├── __init__.py
├── __main__.py
├── base.py
├── entry_points
│ ├── __init__.py
│ ├── database_schema.py
│ ├── dump_fixture.py
│ ├── gen_events.py
│ ├── graph_schema.py
│ ├── init.py
│ ├── load_fixture.py
│ ├── migration_check.py
│ ├── service_account_key.py
│ ├── shell.py
│ └── yoyo.py
├── graph_templates
│ ├── body.html
│ ├── head.html
│ ├── rel.html
│ └── tail.html
├── lib.py
└── tests
│ ├── __init__.py
│ ├── entry_points
│ ├── __init__.py
│ ├── conftest.py
│ └── test_init.py
│ ├── test_imports.py
│ └── test_lib.py
├── common
├── __init__.py
├── actions
│ ├── __init__.py
│ ├── action.py
│ ├── action_factory.py
│ ├── data_points.py
│ ├── send_email_action.py
│ └── webhook_action.py
├── api
│ ├── __init__.py
│ ├── base_view.py
│ ├── flask_ext
│ │ ├── __init__.py
│ │ ├── authentication
│ │ │ ├── __init__.py
│ │ │ ├── common.py
│ │ │ ├── jwt_plugin.py
│ │ │ └── service_account_key_plugin.py
│ │ ├── base_extension.py
│ │ ├── config.py
│ │ ├── cors.py
│ │ ├── database_connection.py
│ │ ├── exception_handling.py
│ │ ├── health.py
│ │ ├── htmx.py
│ │ ├── logging.py
│ │ ├── timing.py
│ │ └── url_converters.py
│ ├── request_parsing.py
│ └── search_view.py
├── apscheduler_extensions.py
├── argparse.py
├── auth
│ ├── __init__.py
│ ├── keys
│ │ ├── __init__.py
│ │ ├── lib.py
│ │ ├── service_key.py
│ │ └── settings.py
│ └── permissions.py
├── constants
│ ├── __init__.py
│ ├── defaults.py
│ ├── email_templates.py
│ ├── peewee.py
│ ├── rbac.py
│ ├── schema_limits.py
│ ├── schema_validation.py
│ └── validation_messages.py
├── datetime_utils.py
├── decorators.py
├── email
│ ├── __init__.py
│ ├── email_renderer.py
│ ├── email_service.py
│ └── templates
│ │ ├── __init__.py
│ │ ├── agent_status_change_template.py
│ │ ├── base_template.py
│ │ ├── instance_alert_template.py
│ │ ├── message_log_template.py
│ │ ├── metric_log_template.py
│ │ ├── run_state_template.py
│ │ ├── task_status_completed_template.py
│ │ ├── task_status_error_template.py
│ │ ├── task_status_missing_template.py
│ │ ├── task_status_pending_template.py
│ │ ├── task_status_started_template.py
│ │ ├── task_status_warning_template.py
│ │ └── test_status_template.py
├── entities
│ ├── __init__.py
│ ├── action.py
│ ├── agent.py
│ ├── alert.py
│ ├── auth_provider.py
│ ├── authentication.py
│ ├── base_entity.py
│ ├── company.py
│ ├── component.py
│ ├── component_meta.py
│ ├── dataset.py
│ ├── dataset_operation.py
│ ├── event.py
│ ├── instance.py
│ ├── instance_rule.py
│ ├── journey.py
│ ├── organization.py
│ ├── pipeline.py
│ ├── project.py
│ ├── rule.py
│ ├── run.py
│ ├── schedule.py
│ ├── server.py
│ ├── streaming_pipeline.py
│ ├── task.py
│ ├── test_outcome.py
│ ├── testgen.py
│ ├── upcoming_instance.py
│ └── user.py
├── entity_services
│ ├── __init__.py
│ ├── agent_service.py
│ ├── company_service.py
│ ├── component_service.py
│ ├── event_service.py
│ ├── helpers
│ │ ├── __init__.py
│ │ ├── filter_rules.py
│ │ └── list_rules.py
│ ├── instance_dag_service.py
│ ├── instance_service.py
│ ├── journey_service.py
│ ├── organization_service.py
│ ├── pipeline_service.py
│ ├── project_service.py
│ ├── run_service.py
│ ├── sa_key_service.py
│ ├── test_outcome_service.py
│ ├── upcoming_instance_service.py
│ └── user_service.py
├── events
│ ├── __init__.py
│ ├── base.py
│ ├── converters.py
│ ├── enums.py
│ ├── event_handler.py
│ ├── internal
│ │ ├── __init__.py
│ │ ├── alert.py
│ │ ├── scheduled_event.py
│ │ ├── scheduled_instance.py
│ │ └── system.py
│ ├── v1
│ │ ├── ARCHITECTURE.md
│ │ ├── __init__.py
│ │ ├── dataset_operation_event.py
│ │ ├── event.py
│ │ ├── event_interface.py
│ │ ├── event_schemas.py
│ │ ├── message_log_event.py
│ │ ├── metric_log_event.py
│ │ ├── run_status_event.py
│ │ ├── test_outcomes_event.py
│ │ └── utils.py
│ └── v2
│ │ ├── __init__.py
│ │ ├── base.py
│ │ ├── batch_pipeline_status.py
│ │ ├── component_data.py
│ │ ├── dataset_operation.py
│ │ ├── helpers.py
│ │ ├── message_log.py
│ │ ├── metric_log.py
│ │ ├── test_outcomes.py
│ │ └── testgen.py
├── exceptions
│ ├── __init__.py
│ └── service.py
├── hash.py
├── join_helpers.py
├── json_encoder.py
├── kafka
│ ├── __init__.py
│ ├── consumer.py
│ ├── errors.py
│ ├── message.py
│ ├── producer.py
│ ├── settings.py
│ └── topic.py
├── kubernetes
│ ├── __init__.py
│ └── readiness_probe.py
├── logging
│ ├── __init__.py
│ └── json_logging.py
├── messagepack.py
├── model.py
├── peewee_extensions
│ ├── __init__.py
│ ├── fields.py
│ ├── fixtures.py
│ └── templates
│ │ └── model.toml
├── plugins.py
├── predicate_engine
│ ├── __init__.py
│ ├── _operators.py
│ ├── compilers
│ │ ├── __init__.py
│ │ ├── simple_v1.py
│ │ └── utils.py
│ ├── exceptions.py
│ ├── query.py
│ └── schemas
│ │ ├── __init__.py
│ │ └── simple_v1.py
├── schemas
│ ├── __init__.py
│ ├── action_schemas.py
│ ├── fields
│ │ ├── __init__.py
│ │ ├── cron_expr_str.py
│ │ ├── enum_str.py
│ │ ├── normalized_str.py
│ │ └── zoneinfo.py
│ ├── filter_schemas.py
│ └── validators
│ │ ├── __init__.py
│ │ ├── not_empty.py
│ │ └── regexp.py
├── sentinel.py
├── tests
│ ├── __init__.py
│ ├── fake_models
│ │ ├── __init__.py
│ │ ├── model_a.py
│ │ └── model_b.py
│ ├── integration
│ │ ├── __init__.py
│ │ ├── actions
│ │ │ ├── __init__.py
│ │ │ ├── test_action_factory.py
│ │ │ ├── test_send_email_action.py
│ │ │ └── test_webhook_action.py
│ │ ├── api
│ │ │ └── __init__.py
│ │ ├── auth
│ │ │ ├── __init__.py
│ │ │ ├── conftest.py
│ │ │ └── test_service_keys.py
│ │ ├── conftest.py
│ │ ├── email
│ │ │ └── __init__.py
│ │ ├── entities
│ │ │ ├── __init__.py
│ │ │ ├── conftest.py
│ │ │ ├── test_action.py
│ │ │ ├── test_alerts.py
│ │ │ ├── test_base_entity.py
│ │ │ ├── test_component_meta.py
│ │ │ ├── test_dataset_operation.py
│ │ │ ├── test_instance.py
│ │ │ ├── test_instance_rules.py
│ │ │ ├── test_pipelines.py
│ │ │ ├── test_rule.py
│ │ │ ├── test_runs.py
│ │ │ ├── test_schedule.py
│ │ │ ├── test_task.py
│ │ │ ├── test_testgen.py
│ │ │ ├── test_testgen_test_outcome_integration.py
│ │ │ └── test_user.py
│ │ ├── entity_services
│ │ │ ├── __init__.py
│ │ │ ├── conftest.py
│ │ │ ├── test_company_service.py
│ │ │ ├── test_component_service.py
│ │ │ ├── test_event_service.py
│ │ │ ├── test_instance_service.py
│ │ │ ├── test_journey_service.py
│ │ │ ├── test_organization_service.py
│ │ │ ├── test_pipeline_service.py
│ │ │ ├── test_project_service.py
│ │ │ ├── test_run_service.py
│ │ │ ├── test_test_outcome_service.py
│ │ │ ├── test_upcoming_instance_services.py
│ │ │ └── test_user_service.py
│ │ ├── events
│ │ │ ├── conftest.py
│ │ │ ├── internal
│ │ │ │ ├── test_alerts.py
│ │ │ │ └── test_base.py
│ │ │ ├── test_base_events.py
│ │ │ └── test_handlers.py
│ │ ├── flask_ext
│ │ │ ├── __init__.py
│ │ │ ├── conftest.py
│ │ │ ├── test_cors.py
│ │ │ ├── test_htmx.py
│ │ │ └── test_service_account_auth.py
│ │ ├── peewee_extensions
│ │ │ ├── __init__.py
│ │ │ ├── bad_fixtures
│ │ │ │ ├── company.toml
│ │ │ │ └── organization.toml
│ │ │ ├── conftest.py
│ │ │ ├── fixtures
│ │ │ │ ├── company.toml
│ │ │ │ ├── organization.toml
│ │ │ │ ├── project.toml
│ │ │ │ └── service-account-key.toml
│ │ │ ├── test_fixture.py
│ │ │ ├── test_json_dict_list_field.py
│ │ │ ├── test_json_schema_field.py
│ │ │ └── test_json_str_list_field.py
│ │ ├── predicate_engine
│ │ │ └── test_compilers_v1.py
│ │ ├── test_apscheduler_extensions.py
│ │ ├── test_config.py
│ │ ├── test_health.py
│ │ └── test_join_helpers.py
│ └── unit
│ │ ├── __init__.py
│ │ ├── actions
│ │ ├── __init__.py
│ │ ├── conftest.py
│ │ ├── test_action_factory.py
│ │ ├── test_base_action.py
│ │ ├── test_send_email_action.py
│ │ └── test_webhook_action.py
│ │ ├── api
│ │ ├── __init__.py
│ │ ├── conftest.py
│ │ ├── test_auth_helpers.py
│ │ ├── test_request_parsing.py
│ │ └── test_search_view.py
│ │ ├── auth
│ │ ├── __init__.py
│ │ └── test_auth_key_lib.py
│ │ ├── constants
│ │ ├── __init__.py
│ │ ├── test_constants.py
│ │ └── test_schema_validation.py
│ │ ├── email
│ │ ├── __init__.py
│ │ └── test_email_service.py
│ │ ├── entities
│ │ ├── __init__.py
│ │ ├── test_component_meta.py
│ │ ├── test_journey_dag.py
│ │ └── test_task.py
│ │ ├── entity_services
│ │ ├── __init__.py
│ │ └── helpers
│ │ │ ├── __init__.py
│ │ │ ├── test_filter_rules.py
│ │ │ └── test_list_rules.py
│ │ ├── events
│ │ ├── __init__.py
│ │ ├── test_converters.py
│ │ ├── v1
│ │ │ ├── __init__.py
│ │ │ ├── conftest.py
│ │ │ ├── test_base_events.py
│ │ │ ├── test_close_run.py
│ │ │ ├── test_dataset_operation_event.py
│ │ │ ├── test_event_schemas.py
│ │ │ ├── test_message_log.py
│ │ │ ├── test_metric_log.py
│ │ │ ├── test_status_event.py
│ │ │ ├── test_testoutcomes.py
│ │ │ └── test_testoutcomesitem.py
│ │ └── v2
│ │ │ ├── conftest.py
│ │ │ ├── test_batch_pipeline_status.py
│ │ │ ├── test_dataset_operation.py
│ │ │ ├── test_event.py
│ │ │ ├── test_message_log.py
│ │ │ ├── test_metric_log.py
│ │ │ ├── test_test_outcomes.py
│ │ │ └── test_testoutcomesitem.py
│ │ ├── flask_ext
│ │ ├── __init__.py
│ │ ├── conftest.py
│ │ ├── test_base_auth_plugin.py
│ │ ├── test_cors.py
│ │ ├── test_exception_handling.py
│ │ └── test_jwt_plugin.py
│ │ ├── kafka
│ │ ├── __init__.py
│ │ ├── conftest.py
│ │ ├── test_consumer.py
│ │ ├── test_producer.py
│ │ └── test_topic.py
│ │ ├── kubernetes
│ │ ├── __init__.py
│ │ └── test_readiness_probe.py
│ │ ├── logging
│ │ ├── __init__.py
│ │ └── test_log_config.py
│ │ ├── peewee_extensions
│ │ ├── __init__.py
│ │ ├── test_fixture.py
│ │ └── test_peewee_extensions.py
│ │ ├── predicate_engine
│ │ ├── __init__.py
│ │ ├── assertions.py
│ │ ├── conftest.py
│ │ ├── test_compilers_v1.py
│ │ ├── test_predicate_engine.py
│ │ └── test_schemas_v1.py
│ │ ├── schemas
│ │ ├── __init__.py
│ │ ├── fields
│ │ │ ├── __init__.py
│ │ │ ├── test_cron_str.py
│ │ │ ├── test_enum_str.py
│ │ │ ├── test_normalized_str.py
│ │ │ └── test_zoneinfo.py
│ │ ├── test_filter_schemas.py
│ │ └── validators
│ │ │ ├── __init__.py
│ │ │ ├── test_is_regexp.py
│ │ │ └── test_not_empty.py
│ │ ├── test_apscheduler_extensions.py
│ │ ├── test_argparse.py
│ │ ├── test_datetime_utils.py
│ │ ├── test_decorators.py
│ │ ├── test_hash.py
│ │ ├── test_json_encoder.py
│ │ ├── test_messagepack.py
│ │ └── test_model_utils.py
├── typing.py
├── user_strings
│ ├── __init__.py
│ └── alert_descriptions.py
└── validate_decorators_type_inference.pyi
├── conf
├── __init__.py
├── cloud.py
├── defaults.py
├── local.py
├── minikube.py
└── test.py
├── conftest.py
├── deploy
├── charts
│ ├── observability-app
│ │ ├── Chart.yaml
│ │ ├── templates
│ │ │ ├── _environments.tpl
│ │ │ ├── _helpers.tpl
│ │ │ ├── _probes.tpl
│ │ │ ├── agent-api.yaml
│ │ │ ├── cli-tool-hook.yaml
│ │ │ ├── event-api.yaml
│ │ │ ├── observability-api.yaml
│ │ │ ├── observability-ui.yaml
│ │ │ ├── rules-engine.yaml
│ │ │ ├── run-manager.yaml
│ │ │ ├── scheduler.yaml
│ │ │ └── serviceaccount.yaml
│ │ └── values.yaml
│ └── observability-services
│ │ ├── Chart.lock
│ │ ├── Chart.yaml
│ │ └── values.yaml
├── charts_values
│ ├── values-app-dev.yaml
│ └── values-services-dev.yaml
├── conf
│ ├── gunicorn.conf.py
│ └── yoyo.ini
├── docker
│ ├── docker-bake.json
│ ├── observability-be.dockerfile
│ └── observability-ui.dockerfile
├── generate_swagger_spec.py
├── migrations
│ ├── 20240605_01_vjN7f-initial-schema.rollback.sql
│ ├── 20240605_01_vjN7f-initial-schema.sql
│ ├── 20240627_01_bgIWR-adding-agent-status-column.py
│ ├── 20240627_02_ORQ6B-adding-agent-status-check-config-column.py
│ ├── 20240627_03_4o7tH-agent-status-check-default-values.py
│ ├── 20240701_01_zRe7i-add-project-alert-config-field.py
│ ├── 20240705_01_37l4A-set-project-alert-config-default.py
│ └── 20240723_01_K3c3Q-renaming-the-agent-check-interval-column.py
├── pages
│ ├── deploy-pages.py
│ └── index.html
├── promote_branch.sh
├── search_view_plugin.py
└── subcomponent_plugin.py
├── event_api
├── __init__.py
├── app.py
├── config
│ ├── __init__.py
│ ├── cloud.py
│ ├── defaults.py
│ ├── local.py
│ ├── minikube.py
│ └── test.py
├── endpoints
│ ├── __init__.py
│ ├── v1
│ │ ├── __init__.py
│ │ ├── dataset_operation.py
│ │ ├── event_view.py
│ │ ├── message_log.py
│ │ ├── metric_log.py
│ │ ├── run_status.py
│ │ └── test_outcomes.py
│ └── v2
│ │ ├── __init__.py
│ │ ├── batch_pipeline_status.py
│ │ ├── dataset_operation.py
│ │ ├── event_view.py
│ │ ├── message_log.py
│ │ ├── metric_log.py
│ │ └── test_outcomes.py
├── helpers
│ ├── __init__.py
│ └── health.py
├── routes
│ ├── __init__.py
│ ├── v1_routes.py
│ └── v2_routes.py
└── tests
│ ├── __init__.py
│ ├── integration
│ ├── __init__.py
│ ├── v1_endpoints
│ │ ├── __init__.py
│ │ ├── conftest.py
│ │ ├── test_dataset_operation.py
│ │ ├── test_event_view.py
│ │ ├── test_message_log.py
│ │ ├── test_metric_log.py
│ │ ├── test_run_status.py
│ │ └── test_testoutcomes.py
│ └── v2_endpoints
│ │ ├── __init__.py
│ │ ├── conftest.py
│ │ ├── test_batch_pipeline_status.py
│ │ ├── test_dataset_operation.py
│ │ ├── test_message_log.py
│ │ ├── test_metric_log.py
│ │ └── test_test_outcomes.py
│ └── unit
│ └── __init__.py
├── fixtures
└── README.md
├── observability_api
├── README.md
├── __init__.py
├── app.py
├── config
│ ├── __init__.py
│ ├── cloud.py
│ ├── defaults.py
│ ├── local.py
│ ├── minikube.py
│ └── test.py
├── endpoints
│ ├── __init__.py
│ ├── component_view.py
│ ├── entity_view.py
│ └── v1
│ │ ├── __init__.py
│ │ ├── actions.py
│ │ ├── agents.py
│ │ ├── alerts.py
│ │ ├── auth.py
│ │ ├── batch_pipelines.py
│ │ ├── companies.py
│ │ ├── components.py
│ │ ├── datasets.py
│ │ ├── instance_rules.py
│ │ ├── instances.py
│ │ ├── journeys.py
│ │ ├── organizations.py
│ │ ├── project_settings.py
│ │ ├── projects.py
│ │ ├── rules.py
│ │ ├── runs.py
│ │ ├── schedules.py
│ │ ├── servers.py
│ │ ├── service_account_keys.py
│ │ ├── streaming_pipelines.py
│ │ ├── tasks.py
│ │ ├── test_outcomes.py
│ │ ├── upcoming_instances.py
│ │ └── users.py
├── helpers
│ ├── __init__.py
│ └── health.py
├── routes
│ ├── __init__.py
│ └── v1_routes.py
├── schemas
│ ├── __init__.py
│ ├── action_schemas.py
│ ├── agent_schemas.py
│ ├── alert_schemas.py
│ ├── base_schemas.py
│ ├── company_schemas.py
│ ├── component_schemas.py
│ ├── dataset_schemas.py
│ ├── event_schemas.py
│ ├── instance_dag_schemas.py
│ ├── instance_rule_schemas.py
│ ├── instance_schemas.py
│ ├── journey_dag_schemas.py
│ ├── journey_schemas.py
│ ├── organization_schemas.py
│ ├── pipeline_schemas.py
│ ├── project_schemas.py
│ ├── rule_schemas.py
│ ├── run_schemas.py
│ ├── schedule_schemas.py
│ ├── server_schemas.py
│ ├── service_account_key_schemas.py
│ ├── streaming_pipeline_schemas.py
│ ├── task_schemas.py
│ ├── testgen_dataset_component_schemas.py
│ ├── testgen_test_outcome_schemas.py
│ ├── upcoming_instance_schemas.py
│ └── user_schemas.py
└── tests
│ ├── __init__.py
│ ├── functional
│ └── __init__.py
│ ├── integration
│ ├── __init__.py
│ ├── helpers
│ │ └── __init__.py
│ ├── schemas
│ │ ├── __init__.py
│ │ ├── conftest.py
│ │ ├── test_agent_schemas.py
│ │ ├── test_alert_schemas.py
│ │ ├── test_event_schemas.py
│ │ ├── test_testgen_component_schemas.py
│ │ └── test_testgen_test_outcome_schemas.py
│ └── v1_endpoints
│ │ ├── __init__.py
│ │ ├── conftest.py
│ │ ├── test_actions.py
│ │ ├── test_agents.py
│ │ ├── test_alerts.py
│ │ ├── test_basic_auth.py
│ │ ├── test_batch_pipelines.py
│ │ ├── test_companies.py
│ │ ├── test_components.py
│ │ ├── test_converters.py
│ │ ├── test_instance_rules.py
│ │ ├── test_instances.py
│ │ ├── test_journeys.py
│ │ ├── test_jwt_auth.py
│ │ ├── test_organizations.py
│ │ ├── test_project_settings.py
│ │ ├── test_projects.py
│ │ ├── test_route_auth.py
│ │ ├── test_rules.py
│ │ ├── test_runs.py
│ │ ├── test_sa_key_auth.py
│ │ ├── test_schedules.py
│ │ ├── test_service_account_keys.py
│ │ ├── test_tasks.py
│ │ ├── test_test_outcomes.py
│ │ ├── test_upcoming_instances.py
│ │ └── test_users.py
│ └── unit
│ ├── __init__.py
│ ├── helpers
│ └── __init__.py
│ ├── schemas
│ ├── test_instance_dag_schema.py
│ ├── test_instance_rule_schema.py
│ ├── test_operations_summary_schema.py
│ ├── test_rule_schema.py
│ ├── test_schedule_schema.py
│ ├── test_service_account_key_schema.py
│ ├── test_test_outcome_schema.py
│ ├── test_testgen_test_outcome_integration_schemas.py
│ └── test_upcoming_instance_schemas.py
│ └── v1_endpoints
│ ├── __init__.py
│ ├── conftest.py
│ ├── test_organizations.py
│ ├── test_projects.py
│ ├── test_service_account_keys.py
│ └── test_users.py
├── observability_ui
├── .editorconfig
├── .eslintrc.json
├── .prettierignore
├── .prettierrc
├── .yarn
│ └── releases
│ │ └── yarn-1.22.21.cjs
├── .yarnrc
├── README.md
├── apps
│ ├── .gitkeep
│ ├── basic-auth
│ │ ├── .eslintrc.json
│ │ ├── jest.config.ts
│ │ ├── module-federation.config.js
│ │ ├── package.json
│ │ ├── project.json
│ │ ├── src
│ │ │ ├── app
│ │ │ │ ├── app.component.ts
│ │ │ │ ├── app.module.ts
│ │ │ │ ├── app.routes.ts
│ │ │ │ ├── authentication
│ │ │ │ │ ├── authentication.component.ts
│ │ │ │ │ ├── authentication.module.ts
│ │ │ │ │ └── authentication.routes.ts
│ │ │ │ ├── login
│ │ │ │ │ ├── login.component.html
│ │ │ │ │ ├── login.component.scss
│ │ │ │ │ ├── login.component.spec.ts
│ │ │ │ │ └── login.component.ts
│ │ │ │ ├── logout
│ │ │ │ │ ├── logout.component.html
│ │ │ │ │ ├── logout.component.scss
│ │ │ │ │ ├── logout.component.spec.ts
│ │ │ │ │ └── logout.component.ts
│ │ │ │ └── services
│ │ │ │ │ └── auth.service.ts
│ │ │ ├── assets
│ │ │ │ ├── .gitkeep
│ │ │ │ └── dk-logo-horizontal.svg
│ │ │ ├── bootstrap.ts
│ │ │ ├── favicon.ico
│ │ │ ├── index.html
│ │ │ ├── main.ts
│ │ │ ├── styles.scss
│ │ │ └── test-setup.ts
│ │ ├── tsconfig.app.json
│ │ ├── tsconfig.editor.json
│ │ ├── tsconfig.json
│ │ ├── tsconfig.spec.json
│ │ ├── webpack.config.js
│ │ └── webpack.prod.config.js
│ └── shell
│ │ ├── .eslintrc.json
│ │ ├── jest.config.ts
│ │ ├── module-federation.config.js
│ │ ├── ngsw-config.json
│ │ ├── package.json
│ │ ├── project.json
│ │ ├── src
│ │ ├── app
│ │ │ ├── app-routing.module.ts
│ │ │ ├── app-version
│ │ │ │ ├── app-version.component.css
│ │ │ │ ├── app-version.component.html
│ │ │ │ ├── app-version.component.spec.ts
│ │ │ │ ├── app-version.component.ts
│ │ │ │ ├── app-version.module.ts
│ │ │ │ ├── app-version.service.spec.ts
│ │ │ │ └── app-version.service.ts
│ │ │ ├── app.component.html
│ │ │ ├── app.component.scss
│ │ │ ├── app.component.spec.ts
│ │ │ ├── app.component.ts
│ │ │ ├── app.module.ts
│ │ │ ├── components
│ │ │ │ ├── default-error-handler
│ │ │ │ │ ├── default-error-handler.component.spec.ts
│ │ │ │ │ ├── default-error-handler.component.ts
│ │ │ │ │ ├── default-error-handler.module.ts
│ │ │ │ │ ├── default-error.handler.spec.ts
│ │ │ │ │ └── default-error.handler.ts
│ │ │ │ ├── email-action
│ │ │ │ │ ├── email-action.component.html
│ │ │ │ │ ├── email-action.component.scss
│ │ │ │ │ ├── email-action.component.ts
│ │ │ │ │ └── email-action.store.ts
│ │ │ │ ├── entry
│ │ │ │ │ ├── entry.component.spec.ts
│ │ │ │ │ └── entry.component.ts
│ │ │ │ ├── header
│ │ │ │ │ ├── header.component.html
│ │ │ │ │ ├── header.component.scss
│ │ │ │ │ ├── header.component.spec.ts
│ │ │ │ │ └── header.component.ts
│ │ │ │ ├── offline
│ │ │ │ │ ├── offline.component.html
│ │ │ │ │ ├── offline.component.scss
│ │ │ │ │ ├── offline.component.spec.ts
│ │ │ │ │ └── offline.component.ts
│ │ │ │ ├── project-alerts
│ │ │ │ │ ├── project-alerts.component.html
│ │ │ │ │ ├── project-alerts.component.scss
│ │ │ │ │ ├── project-alerts.component.spec.ts
│ │ │ │ │ ├── project-alerts.component.ts
│ │ │ │ │ ├── project-alerts.store.spec.ts
│ │ │ │ │ └── project-alerts.store.ts
│ │ │ │ ├── rules-actions
│ │ │ │ │ ├── abstract.rule.spec.ts
│ │ │ │ │ ├── abstract.rule.ts
│ │ │ │ │ ├── action
│ │ │ │ │ │ ├── action-template.component.html
│ │ │ │ │ │ ├── action-template.component.scss
│ │ │ │ │ │ ├── action-template.component.spec.ts
│ │ │ │ │ │ └── action-template.component.ts
│ │ │ │ │ ├── alert
│ │ │ │ │ │ ├── templating-alert.component.scss
│ │ │ │ │ │ ├── templating-alert.component.spec.ts
│ │ │ │ │ │ └── templating-alert.component.ts
│ │ │ │ │ ├── implementations
│ │ │ │ │ │ ├── actions
│ │ │ │ │ │ │ ├── example
│ │ │ │ │ │ │ │ └── example-action.component.ts
│ │ │ │ │ │ │ ├── send-email
│ │ │ │ │ │ │ │ ├── send-email-action.component.spec.ts
│ │ │ │ │ │ │ │ └── send-email-action.component.ts
│ │ │ │ │ │ │ └── webhook
│ │ │ │ │ │ │ │ ├── webhook-action.component.spec.ts
│ │ │ │ │ │ │ │ └── webhook-action.component.ts
│ │ │ │ │ │ └── rules
│ │ │ │ │ │ │ ├── example
│ │ │ │ │ │ │ ├── example-rule-label.component.ts
│ │ │ │ │ │ │ └── example-rule.component.ts
│ │ │ │ │ │ │ ├── instance-has-alert
│ │ │ │ │ │ │ ├── instance-has-alert-rule.component.spec.ts
│ │ │ │ │ │ │ └── instance-has-alert-rule.component.ts
│ │ │ │ │ │ │ ├── message-log
│ │ │ │ │ │ │ ├── message-log-rule.component.spec.ts
│ │ │ │ │ │ │ └── message-log-rule.component.ts
│ │ │ │ │ │ │ ├── metric-log
│ │ │ │ │ │ │ ├── metric-log-rule.component.spec.ts
│ │ │ │ │ │ │ └── metric-log-rule.component.ts
│ │ │ │ │ │ │ ├── run-state
│ │ │ │ │ │ │ ├── run-state-rule.component.scss
│ │ │ │ │ │ │ ├── run-state-rule.component.spec.ts
│ │ │ │ │ │ │ └── run-state-rule.component.ts
│ │ │ │ │ │ │ ├── task-status
│ │ │ │ │ │ │ ├── task-status-rule.component.spec.ts
│ │ │ │ │ │ │ └── task-status-rule.component.ts
│ │ │ │ │ │ │ └── test-status
│ │ │ │ │ │ │ ├── test-status-rule.component.spec.ts
│ │ │ │ │ │ │ └── test-status-rule.component.ts
│ │ │ │ │ ├── label
│ │ │ │ │ │ ├── templating-label.component.spec.ts
│ │ │ │ │ │ └── templating-label.component.ts
│ │ │ │ │ ├── rule-display
│ │ │ │ │ │ ├── rule-display.component.html
│ │ │ │ │ │ ├── rule-display.component.scss
│ │ │ │ │ │ ├── rule-display.component.spec.ts
│ │ │ │ │ │ └── rule-display.component.ts
│ │ │ │ │ ├── rule.model.ts
│ │ │ │ │ ├── rule.service.spec.ts
│ │ │ │ │ ├── rule.service.ts
│ │ │ │ │ ├── rule.store.spec.ts
│ │ │ │ │ ├── rule.store.ts
│ │ │ │ │ └── rules-actions.module.ts
│ │ │ │ ├── sidenav-menu
│ │ │ │ │ ├── sidenav-menu.component.html
│ │ │ │ │ ├── sidenav-menu.component.scss
│ │ │ │ │ ├── sidenav-menu.component.spec.ts
│ │ │ │ │ ├── sidenav-menu.component.ts
│ │ │ │ │ └── sidenav-menu.model.ts
│ │ │ │ ├── summary-item
│ │ │ │ │ ├── summary-item.component.html
│ │ │ │ │ ├── summary-item.component.scss
│ │ │ │ │ ├── summary-item.component.spec.ts
│ │ │ │ │ └── summary-item.component.ts
│ │ │ │ └── summary
│ │ │ │ │ ├── summary.component.html
│ │ │ │ │ ├── summary.component.scss
│ │ │ │ │ ├── summary.component.spec.ts
│ │ │ │ │ └── summary.component.ts
│ │ │ ├── config.ts
│ │ │ ├── core.translation.ts
│ │ │ ├── guards
│ │ │ │ ├── is-online.guard.spec.ts
│ │ │ │ └── is-online.guard.ts
│ │ │ ├── projects
│ │ │ │ ├── api-keys
│ │ │ │ │ ├── add-api-key-modal
│ │ │ │ │ │ ├── add-api-key-modal.component.html
│ │ │ │ │ │ ├── add-api-key-modal.component.scss
│ │ │ │ │ │ ├── add-api-key-modal.component.spec.ts
│ │ │ │ │ │ └── add-api-key-modal.component.ts
│ │ │ │ │ ├── api-keys.component.html
│ │ │ │ │ ├── api-keys.component.scss
│ │ │ │ │ ├── api-keys.component.spec.ts
│ │ │ │ │ ├── api-keys.component.ts
│ │ │ │ │ ├── api-keys.service.spec.ts
│ │ │ │ │ ├── api-keys.service.ts
│ │ │ │ │ ├── api-keys.store.spec.ts
│ │ │ │ │ ├── api-keys.store.ts
│ │ │ │ │ └── delete-keys-modal
│ │ │ │ │ │ ├── delete-key-modal.component.ts
│ │ │ │ │ │ └── delete-keys-modal.component.spec.ts
│ │ │ │ ├── component-panel
│ │ │ │ │ ├── component-panel.component.html
│ │ │ │ │ ├── component-panel.component.spec.ts
│ │ │ │ │ ├── component-panel.component.ts
│ │ │ │ │ ├── component-panel.module.ts
│ │ │ │ │ ├── component-panel.translation.ts
│ │ │ │ │ ├── component.panel.component.scss
│ │ │ │ │ └── delete-component-dialog
│ │ │ │ │ │ ├── delete-component-dialog.component.spec.ts
│ │ │ │ │ │ └── delete-component-dialog.component.ts
│ │ │ │ ├── components
│ │ │ │ │ ├── add-component-dialog
│ │ │ │ │ │ ├── add-component-dialog.component.html
│ │ │ │ │ │ ├── add-component-dialog.component.scss
│ │ │ │ │ │ ├── add-component-dialog.component.spec.ts
│ │ │ │ │ │ ├── add-component-dialog.component.ts
│ │ │ │ │ │ └── add-component-dialog.translation.ts
│ │ │ │ │ ├── component-icon
│ │ │ │ │ │ ├── component-icon.component.spec.ts
│ │ │ │ │ │ └── component-icon.component.ts
│ │ │ │ │ ├── components-list
│ │ │ │ │ │ ├── component-list.translation.ts
│ │ │ │ │ │ ├── components-list.component.html
│ │ │ │ │ │ ├── components-list.component.scss
│ │ │ │ │ │ ├── components-list.component.spec.ts
│ │ │ │ │ │ └── components-list.component.ts
│ │ │ │ │ ├── components-routing.module.ts
│ │ │ │ │ ├── components.module.ts
│ │ │ │ │ ├── components.store.spec.ts
│ │ │ │ │ ├── components.store.ts
│ │ │ │ │ ├── multiple-delete-dialog
│ │ │ │ │ │ ├── multiple-delete-dialog.component.scss
│ │ │ │ │ │ ├── multiple-delete-dialog.component.spec.ts
│ │ │ │ │ │ └── multiple-delete-dialog.component.ts
│ │ │ │ │ └── multiple-journey-dialog.component.ts
│ │ │ │ │ │ ├── multiple-journey-dialog.component.scss
│ │ │ │ │ │ ├── multiple-journey-dialog.component.spec.ts
│ │ │ │ │ │ └── multiple-journey-dialog.component.ts
│ │ │ │ ├── edit-expected-arrival-window
│ │ │ │ │ ├── edit-expected-arrival-window.component.html
│ │ │ │ │ └── edit-expected-arrival-window.component.ts
│ │ │ │ ├── edit-expected-schedule
│ │ │ │ │ ├── edit-expected-schedule.component.html
│ │ │ │ │ └── edit-expected-schedule.component.ts
│ │ │ │ ├── events
│ │ │ │ │ ├── batch-runs
│ │ │ │ │ │ ├── batch-runs.component.html
│ │ │ │ │ │ ├── batch-runs.component.scss
│ │ │ │ │ │ ├── batch-runs.component.spec.ts
│ │ │ │ │ │ └── batch-runs.component.ts
│ │ │ │ │ ├── event-list
│ │ │ │ │ │ ├── event-list.component.html
│ │ │ │ │ │ ├── event-list.component.scss
│ │ │ │ │ │ ├── event-list.component.spec.ts
│ │ │ │ │ │ └── event-list.component.ts
│ │ │ │ │ ├── events-routing.module.ts
│ │ │ │ │ ├── events.component.html
│ │ │ │ │ ├── events.component.scss
│ │ │ │ │ ├── events.component.spec.ts
│ │ │ │ │ ├── events.component.ts
│ │ │ │ │ └── events.module.ts
│ │ │ │ ├── instances
│ │ │ │ │ ├── alerts-dialog
│ │ │ │ │ │ ├── alerts-dialog.component.html
│ │ │ │ │ │ ├── alerts-dialog.component.scss
│ │ │ │ │ │ ├── alerts-dialog.component.spec.ts
│ │ │ │ │ │ └── alerts-dialog.component.ts
│ │ │ │ │ ├── instance-alerts
│ │ │ │ │ │ ├── instance-alerts.component.html
│ │ │ │ │ │ ├── instance-alerts.component.scss
│ │ │ │ │ │ ├── instance-alerts.component.spec.ts
│ │ │ │ │ │ └── instance-alerts.component.ts
│ │ │ │ │ ├── instance-details
│ │ │ │ │ │ ├── instance-details.component.html
│ │ │ │ │ │ ├── instance-details.component.scss
│ │ │ │ │ │ ├── instance-details.component.spec.ts
│ │ │ │ │ │ └── instance-details.component.ts
│ │ │ │ │ ├── instance-events
│ │ │ │ │ │ ├── instance-events.component.html
│ │ │ │ │ │ ├── instance-events.component.scss
│ │ │ │ │ │ ├── instance-events.component.spec.ts
│ │ │ │ │ │ └── instance-events.component.ts
│ │ │ │ │ ├── instance-runs-summary
│ │ │ │ │ │ ├── instance-runs-summary.component.html
│ │ │ │ │ │ ├── instance-runs-summary.component.scss
│ │ │ │ │ │ ├── instance-runs-summary.component.spec.ts
│ │ │ │ │ │ └── instance-runs-summary.component.ts
│ │ │ │ │ ├── instance-runs
│ │ │ │ │ │ ├── instance-runs.component.html
│ │ │ │ │ │ ├── instance-runs.component.scss
│ │ │ │ │ │ ├── instance-runs.component.spec.ts
│ │ │ │ │ │ └── instance-runs.component.ts
│ │ │ │ │ ├── instance-status
│ │ │ │ │ │ ├── instance-status.component.html
│ │ │ │ │ │ ├── instance-status.component.scss
│ │ │ │ │ │ ├── instance-status.component.spec.ts
│ │ │ │ │ │ └── instance-status.component.ts
│ │ │ │ │ ├── instance-tests
│ │ │ │ │ │ ├── instance-tests.component.html
│ │ │ │ │ │ ├── instance-tests.component.scss
│ │ │ │ │ │ ├── instance-tests.component.spec.ts
│ │ │ │ │ │ └── instance-tests.component.ts
│ │ │ │ │ ├── instance-timeline
│ │ │ │ │ │ ├── instance-timeline.component.html
│ │ │ │ │ │ ├── instance-timeline.component.scss
│ │ │ │ │ │ ├── instance-timeline.component.spec.ts
│ │ │ │ │ │ └── instance-timeline.component.ts
│ │ │ │ │ ├── instances-list
│ │ │ │ │ │ ├── instances-list.component.html
│ │ │ │ │ │ ├── instances-list.component.scss
│ │ │ │ │ │ ├── instances-list.component.spec.ts
│ │ │ │ │ │ └── instances-list.component.ts
│ │ │ │ │ ├── instances-routing.module.ts
│ │ │ │ │ ├── instances.module.ts
│ │ │ │ │ └── instances.translation.ts
│ │ │ │ ├── integrations
│ │ │ │ │ ├── integrations-panel
│ │ │ │ │ │ ├── integrations-panel.component.html
│ │ │ │ │ │ ├── integrations-panel.component.scss
│ │ │ │ │ │ ├── integrations-panel.component.spec.ts
│ │ │ │ │ │ └── integrations-panel.component.ts
│ │ │ │ │ ├── integrations-routing.module.ts
│ │ │ │ │ ├── integrations.component.html
│ │ │ │ │ ├── integrations.component.scss
│ │ │ │ │ ├── integrations.component.spec.ts
│ │ │ │ │ ├── integrations.component.ts
│ │ │ │ │ ├── integrations.model.ts
│ │ │ │ │ ├── integrations.module.ts
│ │ │ │ │ ├── integrations.translations.ts
│ │ │ │ │ ├── service-key-form
│ │ │ │ │ │ ├── service-key-form.component.spec.ts
│ │ │ │ │ │ └── service-key-form.component.ts
│ │ │ │ │ ├── tool-selector
│ │ │ │ │ │ ├── get-tool-class.pipe.spec.ts
│ │ │ │ │ │ ├── get-tool-class.pipe.ts
│ │ │ │ │ │ ├── tool-selector.component.spec.ts
│ │ │ │ │ │ └── tool-selector.component.ts
│ │ │ │ │ └── tools
│ │ │ │ │ │ ├── abstract-tool.directive.spec.ts
│ │ │ │ │ │ ├── abstract-tool.directive.ts
│ │ │ │ │ │ ├── agent-script-v2.tpl
│ │ │ │ │ │ ├── agent-script.tpl
│ │ │ │ │ │ ├── airflow-tool
│ │ │ │ │ │ ├── airflow-tool.component.html
│ │ │ │ │ │ ├── airflow-tool.component.spec.ts
│ │ │ │ │ │ └── airflow-tool.component.ts
│ │ │ │ │ │ ├── aws-sqs-tool
│ │ │ │ │ │ ├── aws-sqs-tool.component.html
│ │ │ │ │ │ ├── aws-sqs-tool.component.spec.ts
│ │ │ │ │ │ └── aws-sqs-tool.component.ts
│ │ │ │ │ │ ├── azure-blob-storage-tool
│ │ │ │ │ │ ├── azure-blob-storage-tool.component.html
│ │ │ │ │ │ ├── azure-blob-storage-tool.component.spec.ts
│ │ │ │ │ │ └── azure-blob-storage-tool.component.ts
│ │ │ │ │ │ ├── azure-datafactory-tool
│ │ │ │ │ │ ├── azure-datafactory-tool.component.html
│ │ │ │ │ │ ├── azure-datafactory-tool.component.spec.ts
│ │ │ │ │ │ └── azure-datafactory-tool.component.ts
│ │ │ │ │ │ ├── azure-functions-tool
│ │ │ │ │ │ ├── azure-functions-tool.component.html
│ │ │ │ │ │ ├── azure-functions-tool.component.spec.ts
│ │ │ │ │ │ └── azure-functions-tool.component.ts
│ │ │ │ │ │ ├── azure-synapse-pipelines-tool
│ │ │ │ │ │ ├── azure-synapse-pipelines-tool.component.html
│ │ │ │ │ │ ├── azure-synapse-pipelines-tool.component.spec.ts
│ │ │ │ │ │ └── azure-synapse-pipelines-tool.component.ts
│ │ │ │ │ │ ├── cloud-composer-tool
│ │ │ │ │ │ ├── cloud-composer-tool.component.html
│ │ │ │ │ │ ├── cloud-composer-tool.component.spec.ts
│ │ │ │ │ │ └── cloud-composer-tool.component.ts
│ │ │ │ │ │ ├── databricks-tool
│ │ │ │ │ │ ├── databricks-tool.component.html
│ │ │ │ │ │ ├── databricks-tool.component.spec.ts
│ │ │ │ │ │ └── databricks-tool.component.ts
│ │ │ │ │ │ ├── dbt-core-tool
│ │ │ │ │ │ ├── dbt-core-tool.component.html
│ │ │ │ │ │ ├── dbt-core-tool.component.spec.ts
│ │ │ │ │ │ └── dbt-core-tool.component.ts
│ │ │ │ │ │ ├── fivetran-logs-tool
│ │ │ │ │ │ ├── fivetran-logs-tool.component.html
│ │ │ │ │ │ ├── fivetran-logs-tool.component.spec.ts
│ │ │ │ │ │ └── fivetran-logs-tool.component.ts
│ │ │ │ │ │ ├── power-bi-tool
│ │ │ │ │ │ ├── power-bi-tool.component.html
│ │ │ │ │ │ ├── power-bi-tool.component.spec.ts
│ │ │ │ │ │ └── power-bi-tool.component.ts
│ │ │ │ │ │ ├── qlik-tool
│ │ │ │ │ │ ├── qlik-tool.component.html
│ │ │ │ │ │ ├── qlik-tool.component.spec.ts
│ │ │ │ │ │ └── qlik-tool.component.ts
│ │ │ │ │ │ ├── ssis-tool
│ │ │ │ │ │ ├── ssis-tool.component.html
│ │ │ │ │ │ ├── ssis-tool.component.spec.ts
│ │ │ │ │ │ └── ssis-tool.component.ts
│ │ │ │ │ │ ├── talend-tool
│ │ │ │ │ │ ├── talend-tool.component.html
│ │ │ │ │ │ ├── talend-tool.component.spec.ts
│ │ │ │ │ │ └── talend-tool.component.ts
│ │ │ │ │ │ ├── tool-display.component.scss
│ │ │ │ │ │ ├── tool-display.component.spec.ts
│ │ │ │ │ │ ├── tool-display.component.ts
│ │ │ │ │ │ └── tools-common.scss
│ │ │ │ ├── journey-dag-legend
│ │ │ │ │ ├── journey-dag-legend.component.scss
│ │ │ │ │ └── journey-dag-legend.component.ts
│ │ │ │ ├── journeys
│ │ │ │ │ ├── add-journey-dialog
│ │ │ │ │ │ ├── add-journey-dialog.component.html
│ │ │ │ │ │ ├── add-journey-dialog.component.scss
│ │ │ │ │ │ ├── add-journey-dialog.component.spec.ts
│ │ │ │ │ │ └── add-journey-dialog.component.ts
│ │ │ │ │ ├── journey-details
│ │ │ │ │ │ ├── journey-details.component.html
│ │ │ │ │ │ ├── journey-details.component.scss
│ │ │ │ │ │ ├── journey-details.component.spec.ts
│ │ │ │ │ │ └── journey-details.component.ts
│ │ │ │ │ ├── journey-instance-rules
│ │ │ │ │ │ ├── journey-instance-rules.component.html
│ │ │ │ │ │ ├── journey-instance-rules.component.scss
│ │ │ │ │ │ ├── journey-instance-rules.component.spec.ts
│ │ │ │ │ │ └── journey-instance-rules.component.ts
│ │ │ │ │ ├── journey-relationships
│ │ │ │ │ │ ├── journey-relationships.component.html
│ │ │ │ │ │ ├── journey-relationships.component.scss
│ │ │ │ │ │ ├── journey-relationships.component.spec.ts
│ │ │ │ │ │ └── journey-relationships.component.ts
│ │ │ │ │ ├── journey-rules
│ │ │ │ │ │ ├── journey-rules.component.html
│ │ │ │ │ │ ├── journey-rules.component.scss
│ │ │ │ │ │ ├── journey-rules.component.spec.ts
│ │ │ │ │ │ └── journey-rules.component.ts
│ │ │ │ │ ├── journey-settings
│ │ │ │ │ │ ├── journey-settings.component.html
│ │ │ │ │ │ ├── journey-settings.component.scss
│ │ │ │ │ │ ├── journey-settings.component.spec.ts
│ │ │ │ │ │ └── journey-settings.component.ts
│ │ │ │ │ ├── journeys-list
│ │ │ │ │ │ ├── journeys-list.component.html
│ │ │ │ │ │ ├── journeys-list.component.scss
│ │ │ │ │ │ ├── journeys-list.component.spec.ts
│ │ │ │ │ │ └── journeys-list.component.ts
│ │ │ │ │ ├── journeys-routing.module.ts
│ │ │ │ │ ├── journeys.module.ts
│ │ │ │ │ ├── journeys.store.spec.ts
│ │ │ │ │ ├── journeys.store.ts
│ │ │ │ │ ├── journeys.translation.ts
│ │ │ │ │ └── no-components-dialog
│ │ │ │ │ │ ├── no-components-dialog.component.scss
│ │ │ │ │ │ ├── no-components-dialog.component.spec.ts
│ │ │ │ │ │ └── no-components-dialog.component.ts
│ │ │ │ ├── multiple-component-panel
│ │ │ │ │ ├── multiple-component-panel.component.html
│ │ │ │ │ ├── multiple-component-panel.component.scss
│ │ │ │ │ ├── multiple-component-panel.component.spec.ts
│ │ │ │ │ └── multiple-component-panel.component.ts
│ │ │ │ ├── overview
│ │ │ │ │ ├── overview.component.html
│ │ │ │ │ ├── overview.component.scss
│ │ │ │ │ ├── overview.component.spec.ts
│ │ │ │ │ └── overview.component.ts
│ │ │ │ ├── project-display
│ │ │ │ │ ├── project-display.component.scss
│ │ │ │ │ ├── project-display.component.spec.ts
│ │ │ │ │ └── project-display.component.ts
│ │ │ │ ├── projects.menu.model.ts
│ │ │ │ ├── projects.module.ts
│ │ │ │ ├── projects.translation.ts
│ │ │ │ ├── runs-table
│ │ │ │ │ └── runs-table.module.ts
│ │ │ │ ├── runs
│ │ │ │ │ ├── events-table
│ │ │ │ │ │ ├── events-table.component.html
│ │ │ │ │ │ ├── events-table.component.scss
│ │ │ │ │ │ ├── events-table.component.spec.ts
│ │ │ │ │ │ └── events-table.component.ts
│ │ │ │ │ ├── run-dag
│ │ │ │ │ │ ├── run-dag.component.html
│ │ │ │ │ │ ├── run-dag.component.scss
│ │ │ │ │ │ ├── run-dag.component.spec.ts
│ │ │ │ │ │ └── run-dag.component.ts
│ │ │ │ │ ├── run-details
│ │ │ │ │ │ ├── run-details.component.html
│ │ │ │ │ │ ├── run-details.component.scss
│ │ │ │ │ │ ├── run-details.component.spec.ts
│ │ │ │ │ │ └── run-details.component.ts
│ │ │ │ │ ├── run-events
│ │ │ │ │ │ ├── run-events.component.html
│ │ │ │ │ │ ├── run-events.component.scss
│ │ │ │ │ │ ├── run-events.component.spec.ts
│ │ │ │ │ │ └── run-events.component.ts
│ │ │ │ │ ├── run-tests
│ │ │ │ │ │ ├── run-tests.component.html
│ │ │ │ │ │ ├── run-tests.component.scss
│ │ │ │ │ │ ├── run-tests.component.spec.ts
│ │ │ │ │ │ └── run-tests.component.ts
│ │ │ │ │ ├── run-timeline
│ │ │ │ │ │ ├── run-timeline.component.html
│ │ │ │ │ │ ├── run-timeline.component.scss
│ │ │ │ │ │ ├── run-timeline.component.spec.ts
│ │ │ │ │ │ └── run-timeline.component.ts
│ │ │ │ │ ├── runs-routing.module.ts
│ │ │ │ │ ├── runs-table
│ │ │ │ │ │ ├── run-states
│ │ │ │ │ │ │ ├── run-states.component.html
│ │ │ │ │ │ │ ├── run-states.component.scss
│ │ │ │ │ │ │ ├── run-states.component.spec.ts
│ │ │ │ │ │ │ └── run-states.component.ts
│ │ │ │ │ │ ├── run-time
│ │ │ │ │ │ │ ├── run-time.component.html
│ │ │ │ │ │ │ ├── run-time.component.scss
│ │ │ │ │ │ │ ├── run-time.component.spec.ts
│ │ │ │ │ │ │ └── run-time.component.ts
│ │ │ │ │ │ ├── runs-table.component.html
│ │ │ │ │ │ ├── runs-table.component.scss
│ │ │ │ │ │ ├── runs-table.component.spec.ts
│ │ │ │ │ │ └── runs-table.component.ts
│ │ │ │ │ ├── runs.module.ts
│ │ │ │ │ └── runs.translation.ts
│ │ │ │ ├── settings
│ │ │ │ │ ├── settings.component.html
│ │ │ │ │ ├── settings.component.scss
│ │ │ │ │ ├── settings.component.spec.ts
│ │ │ │ │ └── settings.component.ts
│ │ │ │ ├── task-test-summary
│ │ │ │ │ ├── task-test-summary.component.html
│ │ │ │ │ ├── task-test-summary.component.scss
│ │ │ │ │ ├── task-test-summary.component.spec.ts
│ │ │ │ │ ├── task-test-summary.component.ts
│ │ │ │ │ ├── task-test-summary.utils.spec.ts
│ │ │ │ │ └── task-test-summary.utils.ts
│ │ │ │ └── testgen-integration
│ │ │ │ │ ├── testgen-integration.component.html
│ │ │ │ │ ├── testgen-integration.component.scss
│ │ │ │ │ ├── testgen-integration.component.spec.ts
│ │ │ │ │ ├── testgen-integration.component.ts
│ │ │ │ │ └── testgen-integration.model.ts
│ │ │ ├── services
│ │ │ │ ├── components
│ │ │ │ │ ├── component.abstract.service.spec.ts
│ │ │ │ │ ├── component.abstract.service.ts
│ │ │ │ │ ├── components.service.spec.ts
│ │ │ │ │ └── components.service.ts
│ │ │ │ ├── instances
│ │ │ │ │ ├── instances.service.spec.ts
│ │ │ │ │ └── instances.service.ts
│ │ │ │ ├── journeys
│ │ │ │ │ ├── journeys.mock.ts
│ │ │ │ │ ├── journeys.service.spec.ts
│ │ │ │ │ └── journeys.service.ts
│ │ │ │ ├── project-runs
│ │ │ │ │ ├── project-runs.service.spec.ts
│ │ │ │ │ └── project-runs.service.ts
│ │ │ │ ├── run-events
│ │ │ │ │ ├── run-events.mock.ts
│ │ │ │ │ ├── run-events.service.spec.ts
│ │ │ │ │ └── run-events.service.ts
│ │ │ │ └── run-tasks
│ │ │ │ │ ├── run-tasks.service.spec.ts
│ │ │ │ │ └── run-tasks.service.ts
│ │ │ └── stores
│ │ │ │ ├── dag
│ │ │ │ ├── dag.store.spec.ts
│ │ │ │ └── dag.store.ts
│ │ │ │ ├── instances
│ │ │ │ ├── instances.store.spec.ts
│ │ │ │ └── instances.store.ts
│ │ │ │ ├── run-events
│ │ │ │ ├── run-events.store.spec.ts
│ │ │ │ └── run-events.store.ts
│ │ │ │ ├── run-tasks
│ │ │ │ ├── run-tasks.store.spec.ts
│ │ │ │ └── run-tasks.store.ts
│ │ │ │ └── runs
│ │ │ │ ├── runs.store.spec.ts
│ │ │ │ └── runs.store.ts
│ │ ├── assets
│ │ │ ├── .gitkeep
│ │ │ ├── airflow.svg
│ │ │ ├── apache_impala.svg
│ │ │ ├── autosys.svg
│ │ │ ├── aws_glue.svg
│ │ │ ├── aws_lambda.svg
│ │ │ ├── aws_s3.svg
│ │ │ ├── aws_sagemaker.svg
│ │ │ ├── azure_functions.svg
│ │ │ ├── azure_ml.svg
│ │ │ ├── azure_synapse_pipelines.svg
│ │ │ ├── batch_pipeline.svg
│ │ │ ├── blob_storage.svg
│ │ │ ├── cloud_composer.svg
│ │ │ ├── completed_with_warnings.svg
│ │ │ ├── data_factory.svg
│ │ │ ├── databricks.svg
│ │ │ ├── dataops_automation.svg
│ │ │ ├── dataops_testgen.svg
│ │ │ ├── dataset.svg
│ │ │ ├── dbt_core.svg
│ │ │ ├── dk-logo.svg
│ │ │ ├── fivetran.svg
│ │ │ ├── goanywhere.svg
│ │ │ ├── icons
│ │ │ │ ├── icon-128x128.png
│ │ │ │ ├── icon-144x144.png
│ │ │ │ ├── icon-152x152.png
│ │ │ │ ├── icon-192x192.png
│ │ │ │ ├── icon-384x384.png
│ │ │ │ ├── icon-512x512.png
│ │ │ │ ├── icon-72x72.png
│ │ │ │ └── icon-96x96.png
│ │ │ ├── informatica.svg
│ │ │ ├── loading.svg
│ │ │ ├── logo.svg
│ │ │ ├── module-federation.manifest.json
│ │ │ ├── mssql.svg
│ │ │ ├── neo4j.svg
│ │ │ ├── oracle_database.svg
│ │ │ ├── postgresql.svg
│ │ │ ├── power_bi.svg
│ │ │ ├── python.svg
│ │ │ ├── qlik.svg
│ │ │ ├── redshift.svg
│ │ │ ├── server.svg
│ │ │ ├── snowflake.svg
│ │ │ ├── sqs.svg
│ │ │ ├── streaming_pipeline.svg
│ │ │ ├── tableau.svg
│ │ │ └── talend.svg
│ │ ├── bootstrap.ts
│ │ ├── declarations.d.ts
│ │ ├── environments
│ │ │ ├── environment.json
│ │ │ ├── environment.prod.ts
│ │ │ └── environment.ts
│ │ ├── favicon.ico
│ │ ├── index.html
│ │ ├── main.ts
│ │ ├── manifest.webmanifest
│ │ ├── module-federation.manifest.prod.json
│ │ ├── polyfills.ts
│ │ ├── styles.scss
│ │ └── test-setup.ts
│ │ ├── tsconfig.app.json
│ │ ├── tsconfig.editor.json
│ │ ├── tsconfig.json
│ │ ├── tsconfig.spec.json
│ │ ├── webpack.config.js
│ │ ├── webpack.dev.config.js
│ │ ├── webpack.prod.config.js
│ │ └── webpack.staging.config.js
├── jest.config.ts
├── jest.preset.js
├── lerna.json
├── libs
│ ├── .gitkeep
│ ├── core
│ │ ├── .eslintrc.json
│ │ ├── README.md
│ │ ├── jest.config.ts
│ │ ├── package.json
│ │ ├── project.json
│ │ ├── src
│ │ │ ├── index.ts
│ │ │ ├── lib
│ │ │ │ ├── actions
│ │ │ │ │ ├── abstract-action
│ │ │ │ │ │ ├── abstract-action.directive.spec.ts
│ │ │ │ │ │ └── abstract-action.directive.ts
│ │ │ │ │ ├── actions.model.ts
│ │ │ │ │ └── index.ts
│ │ │ │ ├── config
│ │ │ │ │ ├── app-configuration.ts
│ │ │ │ │ ├── config.service.spec.ts
│ │ │ │ │ ├── config.service.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── provide-from-config.ts
│ │ │ │ ├── core.module.ts
│ │ │ │ ├── decorators
│ │ │ │ │ ├── host-resize
│ │ │ │ │ │ ├── host-resize.ts
│ │ │ │ │ │ └── host-resized.spec.ts
│ │ │ │ │ └── index.ts
│ │ │ │ ├── entities
│ │ │ │ │ ├── agent
│ │ │ │ │ │ ├── agent.model.ts
│ │ │ │ │ │ ├── service
│ │ │ │ │ │ │ ├── agent.service.spec.ts
│ │ │ │ │ │ │ └── agent.service.ts
│ │ │ │ │ │ └── store
│ │ │ │ │ │ │ ├── agent.actions.ts
│ │ │ │ │ │ │ ├── agent.state.ts
│ │ │ │ │ │ │ ├── agent.store.spec.ts
│ │ │ │ │ │ │ └── agent.store.ts
│ │ │ │ │ └── index.ts
│ │ │ │ ├── entity
│ │ │ │ │ ├── entity-default-url.mappings.ts
│ │ │ │ │ ├── entity-type.ts
│ │ │ │ │ ├── entity.model.ts
│ │ │ │ │ ├── entity.service.spec.ts
│ │ │ │ │ ├── entity.service.ts
│ │ │ │ │ ├── entity.store.spec.ts
│ │ │ │ │ ├── entity.store.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── mock
│ │ │ │ │ │ ├── mock.decorator.spec.ts
│ │ │ │ │ │ └── mock.decorator.ts
│ │ │ │ │ ├── read-only-rest-api.service.spec.ts
│ │ │ │ │ └── read-only-rest-api.service.ts
│ │ │ │ ├── guards
│ │ │ │ │ ├── auth.guard.spec.ts
│ │ │ │ │ ├── auth.guard.ts
│ │ │ │ │ ├── no-auth
│ │ │ │ │ │ ├── no-auth.guard.spec.ts
│ │ │ │ │ │ └── no-auth.guard.ts
│ │ │ │ │ ├── reset-stores.guard.spec.ts
│ │ │ │ │ └── reset-stores.guard.ts
│ │ │ │ ├── interceptors
│ │ │ │ │ ├── base-http.interceptor.spec.ts
│ │ │ │ │ ├── base-http.interceptor.ts
│ │ │ │ │ ├── filter-params.interceptor.spec.ts
│ │ │ │ │ ├── filter-params.interceptor.ts
│ │ │ │ │ └── index.ts
│ │ │ │ ├── models
│ │ │ │ │ ├── alert.model.ts
│ │ │ │ │ ├── component.model.ts
│ │ │ │ │ ├── event.model.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── instance.model.ts
│ │ │ │ │ ├── integrations.model.ts
│ │ │ │ │ ├── journey.model.ts
│ │ │ │ │ └── runs.model.ts
│ │ │ │ ├── resolvers
│ │ │ │ │ └── entities
│ │ │ │ │ │ ├── entities.resolver.spec.ts
│ │ │ │ │ │ └── entities.resolver.ts
│ │ │ │ ├── services
│ │ │ │ │ ├── auth
│ │ │ │ │ │ ├── auth.model.ts
│ │ │ │ │ │ ├── session.service.spec.ts
│ │ │ │ │ │ └── session.service.ts
│ │ │ │ │ ├── company
│ │ │ │ │ │ ├── company.model.ts
│ │ │ │ │ │ ├── company.service.spec.ts
│ │ │ │ │ │ └── company.service.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── organization
│ │ │ │ │ │ ├── organization.model.ts
│ │ │ │ │ │ ├── organization.service.spec.ts
│ │ │ │ │ │ └── organization.service.ts
│ │ │ │ │ ├── project
│ │ │ │ │ │ ├── project.model.ts
│ │ │ │ │ │ ├── project.service.spec.ts
│ │ │ │ │ │ ├── project.service.ts
│ │ │ │ │ │ ├── project.store.spec.ts
│ │ │ │ │ │ └── project.store.ts
│ │ │ │ │ └── user
│ │ │ │ │ │ ├── user.model.ts
│ │ │ │ │ │ ├── user.service.spec.ts
│ │ │ │ │ │ └── user.service.ts
│ │ │ │ ├── templating
│ │ │ │ │ ├── abstract-templating.directive.ts
│ │ │ │ │ └── index.ts
│ │ │ │ └── utilities
│ │ │ │ │ ├── batch-runs.utilities.spec.ts
│ │ │ │ │ ├── batch-runs.utilities.ts
│ │ │ │ │ ├── general.utilities.spec.ts
│ │ │ │ │ ├── general.utilities.ts
│ │ │ │ │ ├── instance.utilities.spec.ts
│ │ │ │ │ ├── instance.utilities.ts
│ │ │ │ │ ├── observable.utilities.spec.ts
│ │ │ │ │ ├── observable.utilities.ts
│ │ │ │ │ ├── tools.utilities.spec.ts
│ │ │ │ │ ├── tools.utilities.ts
│ │ │ │ │ ├── validators.spec.ts
│ │ │ │ │ └── validators.ts
│ │ │ └── test-setup.ts
│ │ ├── tsconfig.json
│ │ ├── tsconfig.lib.json
│ │ └── tsconfig.spec.json
│ ├── translate
│ │ ├── .eslintrc.json
│ │ ├── README.md
│ │ ├── jest.config.ts
│ │ ├── package.json
│ │ ├── project.json
│ │ ├── src
│ │ │ ├── index.ts
│ │ │ ├── lib
│ │ │ │ ├── translate.pipe.mock.ts
│ │ │ │ ├── translate.pipe.spec.ts
│ │ │ │ ├── translate.pipe.ts
│ │ │ │ ├── translation.module.ts
│ │ │ │ ├── translation.service.spec.ts
│ │ │ │ └── translation.service.ts
│ │ │ └── test-setup.ts
│ │ ├── tsconfig.json
│ │ ├── tsconfig.lib.json
│ │ └── tsconfig.spec.json
│ ├── ui
│ │ ├── .eslintrc.json
│ │ ├── README.md
│ │ ├── jest.config.ts
│ │ ├── package.json
│ │ ├── project.json
│ │ ├── src
│ │ │ ├── index.ts
│ │ │ ├── lib
│ │ │ │ ├── alert
│ │ │ │ │ ├── alert.component.scss
│ │ │ │ │ ├── alert.component.spec.ts
│ │ │ │ │ └── alert.component.ts
│ │ │ │ ├── breadcrumb
│ │ │ │ │ ├── breadcrumb.component.html
│ │ │ │ │ ├── breadcrumb.component.scss
│ │ │ │ │ ├── breadcrumb.component.spec.ts
│ │ │ │ │ ├── breadcrumb.component.ts
│ │ │ │ │ ├── breadcrumb.model.ts
│ │ │ │ │ └── breadcrumb.module.ts
│ │ │ │ ├── code-snippet
│ │ │ │ │ ├── code-snippet.component.html
│ │ │ │ │ ├── code-snippet.component.scss
│ │ │ │ │ ├── code-snippet.component.spec.ts
│ │ │ │ │ └── code-snippet.component.ts
│ │ │ │ ├── confirm-dialog
│ │ │ │ │ ├── confirm-dialog.component.scss
│ │ │ │ │ ├── confirm-dialog.component.spec.ts
│ │ │ │ │ └── confirm-dialog.component.ts
│ │ │ │ ├── created-by
│ │ │ │ │ ├── created-by.component.spec.ts
│ │ │ │ │ └── created-by.component.ts
│ │ │ │ ├── dag
│ │ │ │ │ ├── dag-actions
│ │ │ │ │ │ ├── dag-actions.component.html
│ │ │ │ │ │ ├── dag-actions.component.scss
│ │ │ │ │ │ ├── dag-actions.component.spec.ts
│ │ │ │ │ │ └── dag-actions.component.ts
│ │ │ │ │ ├── dag-edge.directive.spec.ts
│ │ │ │ │ ├── dag-edge.directive.ts
│ │ │ │ │ ├── dag-legend.directive.spec.ts
│ │ │ │ │ ├── dag-legend.directive.ts
│ │ │ │ │ ├── dag-node.directive.spec.ts
│ │ │ │ │ ├── dag-node.directive.ts
│ │ │ │ │ ├── dag.component.html
│ │ │ │ │ ├── dag.component.scss
│ │ │ │ │ ├── dag.component.spec.ts
│ │ │ │ │ ├── dag.component.ts
│ │ │ │ │ ├── dag.model.ts
│ │ │ │ │ ├── dag.module.ts
│ │ │ │ │ ├── dag.translation.ts
│ │ │ │ │ └── index.ts
│ │ │ │ ├── details-header
│ │ │ │ │ ├── details-header.component.html
│ │ │ │ │ ├── details-header.component.scss
│ │ │ │ │ ├── details-header.component.spec.ts
│ │ │ │ │ ├── details-header.component.ts
│ │ │ │ │ ├── details-header.module.ts
│ │ │ │ │ └── index.ts
│ │ │ │ ├── directives
│ │ │ │ │ ├── bind-query-params
│ │ │ │ │ │ ├── bind-query-params.abstract.spec.ts
│ │ │ │ │ │ ├── bind-query-params.abstract.ts
│ │ │ │ │ │ ├── bind-query-params.module.ts
│ │ │ │ │ │ ├── to-mat-paginator
│ │ │ │ │ │ │ ├── bind-query-params-mat-paginator.directive.spec.ts
│ │ │ │ │ │ │ └── bind-query-params-mat-paginator.directive.ts
│ │ │ │ │ │ ├── to-mat-sort
│ │ │ │ │ │ │ ├── bind-query-params-mat-sort.directive.spec.ts
│ │ │ │ │ │ │ └── bind-query-params-mat-sort.directive.ts
│ │ │ │ │ │ └── to-mat-tab
│ │ │ │ │ │ │ ├── bind-query-params-mat-tab.directive.spec.ts
│ │ │ │ │ │ │ └── bind-query-params-mat-tab.directive.ts
│ │ │ │ │ ├── click-confirm
│ │ │ │ │ │ ├── click-confirm.directive.spec.ts
│ │ │ │ │ │ └── click-confirm.directive.ts
│ │ │ │ │ ├── dynamic-component
│ │ │ │ │ │ ├── dynamic-component-outlet.directive.spec.ts
│ │ │ │ │ │ ├── dynamic-component-outlet.directive.ts
│ │ │ │ │ │ ├── dynamic-component.module.ts
│ │ │ │ │ │ └── index.ts
│ │ │ │ │ └── index.ts
│ │ │ │ ├── dk-tooltip
│ │ │ │ │ ├── click-listener.service.spec.ts
│ │ │ │ │ ├── click-listener.service.ts
│ │ │ │ │ ├── dk-tooltip.component.html
│ │ │ │ │ ├── dk-tooltip.component.scss
│ │ │ │ │ ├── dk-tooltip.component.spec.ts
│ │ │ │ │ ├── dk-tooltip.component.ts
│ │ │ │ │ ├── dk-tooltip.directive.spec.ts
│ │ │ │ │ ├── dk-tooltip.directive.ts
│ │ │ │ │ ├── dk-tooltip.model.ts
│ │ │ │ │ ├── dk-tooltip.module.ts
│ │ │ │ │ └── index.ts
│ │ │ │ ├── dots-chart
│ │ │ │ │ ├── dot-template.directive.ts
│ │ │ │ │ ├── dot.component.scss
│ │ │ │ │ ├── dot.component.spec.ts
│ │ │ │ │ ├── dot.component.ts
│ │ │ │ │ ├── dots-chart.component.html
│ │ │ │ │ ├── dots-chart.component.scss
│ │ │ │ │ ├── dots-chart.component.spec.ts
│ │ │ │ │ ├── dots-chart.component.ts
│ │ │ │ │ └── drill-in.directive.ts
│ │ │ │ ├── duration
│ │ │ │ │ ├── duration.component.spec.ts
│ │ │ │ │ ├── duration.component.ts
│ │ │ │ │ ├── duration.module.ts
│ │ │ │ │ ├── duration.pipe.spec.ts
│ │ │ │ │ ├── duration.pipe.ts
│ │ │ │ │ └── index.ts
│ │ │ │ ├── element-ref
│ │ │ │ │ ├── element-ref.directive.spec.ts
│ │ │ │ │ └── element-ref.directive.ts
│ │ │ │ ├── empty-state-setup
│ │ │ │ │ ├── empty-state-setup.component.html
│ │ │ │ │ ├── empty-state-setup.component.scss
│ │ │ │ │ ├── empty-state-setup.component.spec.ts
│ │ │ │ │ └── empty-state-setup.component.ts
│ │ │ │ ├── entity
│ │ │ │ │ ├── active-status-chip
│ │ │ │ │ │ ├── active-status-chip.component.html
│ │ │ │ │ │ ├── active-status-chip.component.spec.ts
│ │ │ │ │ │ └── active-status-chip.component.ts
│ │ │ │ │ ├── entity-list-placeholder
│ │ │ │ │ │ ├── entity-list-placeholder.component.html
│ │ │ │ │ │ ├── entity-list-placeholder.component.scss
│ │ │ │ │ │ ├── entity-list-placeholder.component.spec.ts
│ │ │ │ │ │ └── entity-list-placeholder.component.ts
│ │ │ │ │ ├── entity.module.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── nullify-pending
│ │ │ │ │ │ ├── nullify-pending.pipe.spec.ts
│ │ │ │ │ │ └── nullify-pending.pipe.ts
│ │ │ │ ├── expansion-panel
│ │ │ │ │ ├── expansion-panel-content
│ │ │ │ │ │ ├── expansion-panel-content.component.spec.ts
│ │ │ │ │ │ └── expansion-panel-content.component.ts
│ │ │ │ │ ├── expansion-panel-title
│ │ │ │ │ │ ├── expansion-panel-title.component.spec.ts
│ │ │ │ │ │ └── expansion-panel-title.component.ts
│ │ │ │ │ ├── expansion-panel.module.ts
│ │ │ │ │ ├── expansion-panel
│ │ │ │ │ │ ├── expansion-panel.component.html
│ │ │ │ │ │ ├── expansion-panel.component.scss
│ │ │ │ │ │ ├── expansion-panel.component.spec.ts
│ │ │ │ │ │ └── expansion-panel.component.ts
│ │ │ │ │ └── index.ts
│ │ │ │ ├── fields
│ │ │ │ │ ├── abstract-field.spec.ts
│ │ │ │ │ ├── abstract-field.ts
│ │ │ │ │ ├── abstract-mat-form-field-control.directive.spec.ts
│ │ │ │ │ ├── abstract-mat-form-field-control.directive.ts
│ │ │ │ │ ├── checkbox-field
│ │ │ │ │ │ ├── checkbox-field.component.html
│ │ │ │ │ │ ├── checkbox-field.component.scss
│ │ │ │ │ │ ├── checkbox-field.component.spec.ts
│ │ │ │ │ │ ├── checkbox-field.component.ts
│ │ │ │ │ │ └── checkbox-field.module.ts
│ │ │ │ │ ├── filter-field
│ │ │ │ │ │ ├── filter-field-option.component.ts
│ │ │ │ │ │ ├── filter-field.component.html
│ │ │ │ │ │ ├── filter-field.component.scss
│ │ │ │ │ │ ├── filter-field.component.spec.ts
│ │ │ │ │ │ ├── filter-field.component.ts
│ │ │ │ │ │ └── filter-field.module.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── schedule-field
│ │ │ │ │ │ ├── schedule-field.component.html
│ │ │ │ │ │ ├── schedule-field.component.scss
│ │ │ │ │ │ ├── schedule-field.component.spec.ts
│ │ │ │ │ │ ├── schedule-field.component.ts
│ │ │ │ │ │ ├── schedule-field.model.ts
│ │ │ │ │ │ ├── schedule-field.module.ts
│ │ │ │ │ │ ├── schedule.pipe.spec.ts
│ │ │ │ │ │ └── schedule.pipe.ts
│ │ │ │ │ ├── text-field
│ │ │ │ │ │ ├── text-field-error.component.spec.ts
│ │ │ │ │ │ ├── text-field-error.component.ts
│ │ │ │ │ │ ├── text-field.component.html
│ │ │ │ │ │ ├── text-field.component.scss
│ │ │ │ │ │ ├── text-field.component.spec.ts
│ │ │ │ │ │ ├── text-field.component.ts
│ │ │ │ │ │ └── text-field.module.ts
│ │ │ │ │ └── timespan-field
│ │ │ │ │ │ ├── timespan-field.component.html
│ │ │ │ │ │ ├── timespan-field.component.scss
│ │ │ │ │ │ ├── timespan-field.component.spec.ts
│ │ │ │ │ │ ├── timespan-field.component.ts
│ │ │ │ │ │ ├── timespan-field.module.ts
│ │ │ │ │ │ ├── timespan.pipe.spec.ts
│ │ │ │ │ │ ├── timespan.pipe.ts
│ │ │ │ │ │ └── timespan.translation.ts
│ │ │ │ ├── gantt-chart
│ │ │ │ │ ├── gantt-bar.directive.spec.ts
│ │ │ │ │ ├── gantt-bar.directive.ts
│ │ │ │ │ ├── gantt-chart.component.html
│ │ │ │ │ ├── gantt-chart.component.scss
│ │ │ │ │ ├── gantt-chart.component.spec.ts
│ │ │ │ │ ├── gantt-chart.component.ts
│ │ │ │ │ ├── gantt-chart.model.ts
│ │ │ │ │ ├── gantt-chart.module.ts
│ │ │ │ │ ├── gantt-label.directive.ts
│ │ │ │ │ ├── gantt-task.component.spec.ts
│ │ │ │ │ └── gantt-task.component.ts
│ │ │ │ ├── help-link
│ │ │ │ │ ├── help-link.component.spec.ts
│ │ │ │ │ └── help-link.component.ts
│ │ │ │ ├── is-today
│ │ │ │ │ ├── is-today.pipe.spec.ts
│ │ │ │ │ └── is-today.pipe.ts
│ │ │ │ ├── labeled-menu
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── labeled-menu.component.html
│ │ │ │ │ ├── labeled-menu.component.scss
│ │ │ │ │ ├── labeled-menu.component.spec.ts
│ │ │ │ │ ├── labeled-menu.component.ts
│ │ │ │ │ └── labeled-menu.module.ts
│ │ │ │ ├── mat-card-edit
│ │ │ │ │ ├── mat-card-edit.component.html
│ │ │ │ │ ├── mat-card-edit.component.scss
│ │ │ │ │ ├── mat-card-edit.component.spec.ts
│ │ │ │ │ └── mat-card-edit.component.ts
│ │ │ │ ├── metadata-viewer
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── metadata-viewer.component.html
│ │ │ │ │ ├── metadata-viewer.component.scss
│ │ │ │ │ ├── metadata-viewer.component.spec.ts
│ │ │ │ │ ├── metadata-viewer.component.ts
│ │ │ │ │ └── metadata-viewer.module.ts
│ │ │ │ ├── pipes
│ │ │ │ │ ├── get-integration
│ │ │ │ │ │ ├── get-integration.pipe.spec.ts
│ │ │ │ │ │ └── get-integration.pipe.ts
│ │ │ │ │ ├── humanize
│ │ │ │ │ │ ├── humanize.pipe.spec.ts
│ │ │ │ │ │ └── humanize.pipe.ts
│ │ │ │ │ ├── parseDate
│ │ │ │ │ │ ├── parseDate.pipe.spec.ts
│ │ │ │ │ │ └── parseDate.pipe.ts
│ │ │ │ │ └── sum
│ │ │ │ │ │ ├── sum.pipe.spec.ts
│ │ │ │ │ │ └── sum.pipe.ts
│ │ │ │ ├── selected-actions
│ │ │ │ │ ├── selected-actions.component.html
│ │ │ │ │ ├── selected-actions.component.scss
│ │ │ │ │ ├── selected-actions.component.spec.ts
│ │ │ │ │ └── selected-actions.component.ts
│ │ │ │ ├── table-wrapper
│ │ │ │ │ ├── drag-disabled.directive.spec.ts
│ │ │ │ │ ├── drag-disabled.directive.ts
│ │ │ │ │ ├── header-label.directive.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── sort-disabled.directive.spec.ts
│ │ │ │ │ ├── sort-disabled.directive.ts
│ │ │ │ │ ├── table-wrapper-actions.component.spec.ts
│ │ │ │ │ ├── table-wrapper-actions.component.ts
│ │ │ │ │ ├── table-wrapper.component.html
│ │ │ │ │ ├── table-wrapper.component.scss
│ │ │ │ │ ├── table-wrapper.component.spec.ts
│ │ │ │ │ ├── table-wrapper.component.ts
│ │ │ │ │ ├── table-wrapper.model.ts
│ │ │ │ │ ├── table-wrapper.module.ts
│ │ │ │ │ ├── table-wrapper.translation.ts
│ │ │ │ │ ├── toggle-disabled.directive.spec.ts
│ │ │ │ │ └── toggle-disabled.directive.ts
│ │ │ │ ├── truncate
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── truncate.directive.spec.ts
│ │ │ │ │ ├── truncate.directive.ts
│ │ │ │ │ └── truncate.module.ts
│ │ │ │ └── ui.module.ts
│ │ │ └── test-setup.ts
│ │ ├── styles
│ │ │ ├── _details-page.scss
│ │ │ ├── _dialog.scss
│ │ │ ├── _fields.scss
│ │ │ ├── _fx-flex.scss
│ │ │ ├── _gantt-chart.scss
│ │ │ ├── _icon-size.scss
│ │ │ ├── _list-page.scss
│ │ │ ├── _mixins.scss
│ │ │ ├── _overlay.scss
│ │ │ ├── _rules.scss
│ │ │ ├── _spacing.scss
│ │ │ ├── _theme.scss
│ │ │ ├── _variables.scss
│ │ │ └── material
│ │ │ │ └── colors.scss
│ │ ├── tsconfig.json
│ │ ├── tsconfig.lib.json
│ │ └── tsconfig.spec.json
│ └── webpack-config
│ │ ├── index.js
│ │ ├── libs.js
│ │ ├── mapped-paths.js
│ │ └── package.json
├── migrations.json
├── nginx.conf
├── nx.json
├── package.json
├── tools
│ ├── executors
│ │ └── version
│ │ │ ├── executor.json
│ │ │ ├── impl.js
│ │ │ ├── impl.ts
│ │ │ ├── package.json
│ │ │ └── schema.json
│ └── tsconfig.tools.json
├── tsconfig.base.json
└── yarn.lock
├── pyproject.toml
├── rules_engine
├── __init__.py
├── __main__.py
├── engine.py
├── journey_rules.py
├── lib.py
├── project_rules.py
├── rule_data.py
├── tests
│ ├── __init__.py
│ ├── integration
│ │ ├── __init__.py
│ │ ├── conftest.py
│ │ ├── test_rule_data.py
│ │ ├── test_rules.py
│ │ └── test_rules_engine.py
│ └── unit
│ │ ├── __init__.py
│ │ ├── actions
│ │ └── __init__.py
│ │ ├── conftest.py
│ │ ├── test_data_points.py
│ │ └── test_engine.py
└── typing.py
├── run_manager
├── __init__.py
├── __main__.py
├── alerts.py
├── context.py
├── event_handlers
│ ├── __init__.py
│ ├── component_identifier.py
│ ├── dataset_handler.py
│ ├── incomplete_instance_handler.py
│ ├── instance_handler.py
│ ├── out_of_sequence_instance_handler.py
│ ├── run_handler.py
│ ├── run_unexpected_status_change_handler.py
│ ├── schedule_handlers.py
│ ├── scheduled_instance_handler.py
│ ├── task_handler.py
│ ├── test_outcome_handler.py
│ └── utils.py
├── run_manager.py
└── tests
│ ├── __init__.py
│ ├── integration
│ ├── __init__.py
│ ├── conftest.py
│ ├── event_handlers
│ │ ├── __init__.py
│ │ ├── test_component_identifier.py
│ │ ├── test_incomplete_instance_handler.py
│ │ └── test_out_of_sequence_instance_handler.py
│ ├── test_alerts.py
│ ├── test_dataset_handler.py
│ ├── test_instance_handler.py
│ ├── test_run_handler.py
│ ├── test_run_identifier.py
│ ├── test_run_manager.py
│ ├── test_run_manager_instance.py
│ ├── test_run_manager_payload_instance.py
│ ├── test_run_manager_tasks.py
│ ├── test_run_manager_test_outcomes.py
│ ├── test_run_manager_unordered_events.py
│ ├── test_scheduled_instance_handler.py
│ ├── test_scheduler_events.py
│ ├── test_task_handler.py
│ └── test_test_outcome_handler.py
│ └── unit
│ ├── __init__.py
│ ├── conftest.py
│ ├── test_run_manager.py
│ └── test_schedule_handlers.py
├── scheduler
├── __init__.py
├── __main__.py
├── agent_check.py
├── component_expectations.py
├── instance_expectations.py
├── schedule_source.py
└── tests
│ ├── __init__.py
│ ├── integration
│ ├── __init__.py
│ ├── conftest.py
│ ├── test_agent_scheduler.py
│ └── test_schedule_source.py
│ └── unit
│ ├── __init__.py
│ ├── conftest.py
│ ├── test_agent_scheduler.py
│ ├── test_component_scheduler.py
│ ├── test_instance_scheduler.py
│ └── test_schedule_source.py
├── scripts
├── __init__.py
├── check-docker-extensions.py
├── check-tests-are-marked.py
└── invocations
│ ├── __init__.py
│ ├── common.py
│ ├── deploy.py
│ ├── dev.py
│ └── test.py
├── setup.cfg
├── subcommand
├── README.md
├── __init__.py
├── subcmd.py
└── tests
│ ├── __init__.py
│ └── test_subcommand.py
├── tasks.py
└── testlib
├── __init__.py
├── fixtures
├── __init__.py
├── entities.py
├── internal_events.py
├── v1_events.py
├── v2_events.py
└── web_server.py
└── peewee.py
/.dockerignore:
--------------------------------------------------------------------------------
1 | **/__pycache__/
2 | **/tests/
3 | *.egg-info/
4 | *.md
5 | */collaborate_swagger_spec.yaml
6 | */observability_swagger_spec.yaml
7 | .git*
8 | .idea/
9 | .mypy_cache/
10 | .pytest_cache/
11 | .venv/
12 | build/
13 | dist/
14 | instance/
15 | **/node_modules/
16 | node_modules/
17 | scripts/
18 | venv/
19 | **/.angular/
20 | .angular/
21 | .env*
22 | .assets/
23 | .serverless/
24 | tmp/
25 | reports/
26 | .prettierignore
27 | prettierrc
28 | !.env.project
29 | !.env.vault
30 | serverless.yml
31 |
--------------------------------------------------------------------------------
/.github/workflows/release.yaml:
--------------------------------------------------------------------------------
1 | name: Release New Version
2 | on:
3 | push:
4 | branches:
5 | - main
6 | workflow_dispatch:
7 | branches:
8 | - main
9 | jobs:
10 | publish:
11 | runs-on: ubuntu-latest
12 | steps:
13 | - name: Checkout Latest Changes
14 | uses: actions/checkout@v4
15 | with:
16 | fetch-depth: 0
17 |
18 | - name: Package and Publish Charts
19 | uses: ./.github/actions/publish_charts
20 | with:
21 | github-token: '${{ secrets.GITHUB_TOKEN }}'
22 |
--------------------------------------------------------------------------------
/.redocly.lint-ignore.yaml:
--------------------------------------------------------------------------------
1 | # This file instructs Redocly's linter to ignore the rules contained for specific parts of your API.
2 | # See https://redoc.ly/docs/cli/ for more information.
3 | observability_swagger_spec.yaml:
4 | operation-4xx-response:
5 | - '#/paths/~1observability~1v1~1instances/get/responses'
6 | - '#/paths/~1observability~1v1~1upcoming-instances/get/responses'
7 |
--------------------------------------------------------------------------------
/.redocly.yaml:
--------------------------------------------------------------------------------
1 | extends:
2 | - recommended
3 |
4 | apis:
5 | observability@v1:
6 | root: ./observability_swagger_spec.yaml
7 | rules:
8 | operation-summary: off
9 | no-unused-components: off
10 | event@v1:
11 | root: ./events_swagger_spec_v1.yaml
12 | event@v2:
13 | root: ./events_swagger_spec_v2.yaml
14 |
--------------------------------------------------------------------------------
/NOTICE:
--------------------------------------------------------------------------------
1 | DataKitchen DataOps Observability
2 | Copyright 2024 DataKitchen, Inc.
3 |
4 | This product includes software developed at
5 | DataKitchen, Inc. (https://datakitchen.io/).
6 |
--------------------------------------------------------------------------------
/agent_api/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/agent_api/__init__.py
--------------------------------------------------------------------------------
/agent_api/config/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/agent_api/config/__init__.py
--------------------------------------------------------------------------------
/agent_api/config/cloud.py:
--------------------------------------------------------------------------------
1 | import os
2 |
3 | # Flask specific settings: https://flask.palletsprojects.com/en/latest/config/#builtin-configuration-values
4 | SECRET_KEY: str = os.environ["AGENT_API_KEY_FLASK_SECRET"]
5 | SERVER_NAME: str = os.environ["AGENT_API_HOSTNAME"]
6 |
--------------------------------------------------------------------------------
/agent_api/config/local.py:
--------------------------------------------------------------------------------
1 | from typing import Optional
2 |
3 | # Flask specific settings: https://flask.palletsprojects.com/en/latest/config/#builtin-configuration-values
4 | PROPAGATE_EXCEPTIONS: Optional[bool] = True
5 | SECRET_KEY: str = "NOT_VERY_SECRET"
6 |
--------------------------------------------------------------------------------
/agent_api/config/minikube.py:
--------------------------------------------------------------------------------
1 | from typing import Optional
2 |
3 | # Flask specific settings: https://flask.palletsprojects.com/en/latest/config/#builtin-configuration-values
4 | TESTING: Optional[bool] = True
5 | SECRET_KEY: str = "NOT_VERY_SECRET"
6 |
--------------------------------------------------------------------------------
/agent_api/config/test.py:
--------------------------------------------------------------------------------
1 | from peewee import SqliteDatabase
2 |
3 | DATABASE = {
4 | "name": "file:cachedb?mode=memory&cache=shared",
5 | "engine": SqliteDatabase,
6 | "pragmas": {},
7 | }
8 | """Configures an in-memory database with a shared cache for testing."""
9 |
10 | API_PREFIX: str = "agent"
11 |
12 | TESTING: bool = True
13 | """Enable flask TESTING mode. This is needed to get around the default-key security check."""
14 |
--------------------------------------------------------------------------------
/agent_api/endpoints/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/agent_api/endpoints/__init__.py
--------------------------------------------------------------------------------
/agent_api/endpoints/v1/__init__.py:
--------------------------------------------------------------------------------
1 | from .heartbeat import *
2 |
--------------------------------------------------------------------------------
/agent_api/helpers/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/agent_api/helpers/__init__.py
--------------------------------------------------------------------------------
/agent_api/helpers/health.py:
--------------------------------------------------------------------------------
1 | from common.entities import DB
2 | from common.kubernetes.readiness_probe import NotReadyException
3 |
4 |
5 | def readiness_probe() -> None:
6 | if DB.obj is None:
7 | raise NotReadyException("Database not initialized")
8 |
--------------------------------------------------------------------------------
/agent_api/routes/__init__.py:
--------------------------------------------------------------------------------
1 | from .v1_routes import *
2 |
--------------------------------------------------------------------------------
/agent_api/schemas/__init__.py:
--------------------------------------------------------------------------------
1 | from .heartbeat import *
2 |
--------------------------------------------------------------------------------
/agent_api/schemas/heartbeat.py:
--------------------------------------------------------------------------------
1 | __all__ = ("HeartbeatSchema",)
2 |
3 | from marshmallow import Schema
4 | from marshmallow.fields import AwareDateTime, String
5 | from marshmallow.validate import Length
6 |
7 |
8 | class HeartbeatSchema(Schema):
9 | key = String(required=True, validate=Length(max=255))
10 | tool = String(required=True, validate=Length(max=255))
11 | version = String(required=True, validate=Length(max=255))
12 | latest_event_timestamp = AwareDateTime(format="iso", load_default=None, dump_default=None)
13 |
--------------------------------------------------------------------------------
/agent_api/tests/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/agent_api/tests/__init__.py
--------------------------------------------------------------------------------
/agent_api/tests/integration/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/agent_api/tests/integration/__init__.py
--------------------------------------------------------------------------------
/agent_api/tests/integration/v1_endpoints/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/agent_api/tests/integration/v1_endpoints/__init__.py
--------------------------------------------------------------------------------
/benchmark/README.md:
--------------------------------------------------------------------------------
1 | # Benchmarks
2 |
3 | Scripts in this folder are intended to be used to validate performance of implementations.
4 |
5 | ## Cached Property
6 | The ``cached_property.py`` benchmark compares the ``common.decorators`` implementation of ``cached_property`` with
7 | the standard library implementation as well as the one included with ``boltons``.
8 |
9 | To run the benchmark from the ``observability`` project root, first make sure you've activated your virtual environment,
10 | then follow these steps.
11 |
12 | Install benchmarking requirements:
13 | ```bash
14 | $ python -m pip install -r benchmark/requirements.txt
15 | ```
16 |
17 | Run the benchmark
18 | ```bash
19 | $ python benchmark/cached_property.py
20 | ```
21 |
--------------------------------------------------------------------------------
/benchmark/requirements.txt:
--------------------------------------------------------------------------------
1 | boltons>=23.0
2 | pyperf>=2.6
3 |
--------------------------------------------------------------------------------
/cli/entry_points/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/cli/entry_points/__init__.py
--------------------------------------------------------------------------------
/cli/graph_templates/head.html:
--------------------------------------------------------------------------------
1 | digraph name {
2 | fontname = "Helvetica"
3 | fontsize = 8
4 | node [
5 | fontname = "Helvetica"
6 | fontsize = 8
7 | shape = "plaintext"
8 | ]
9 | edge [
10 | fontname = "Helvetica"
11 | fontsize = 8
12 | ]
13 | overlap=false
14 |
--------------------------------------------------------------------------------
/cli/graph_templates/rel.html:
--------------------------------------------------------------------------------
1 | {% for model in models %}{% for relation in model.relations %}{% if relation.needs_node %}{{ relation.target_app }}_{{ relation.target }} [label=<
2 |
3 |
4 | {{ relation.target }} |
5 |
6 | >]
7 | {% endif %}
8 | {{ model.app_name }}_{{ model.name }} -> {{ relation.target_app }}_{{ relation.target }}
9 | [label="{{ relation.label }}"] {{ relation.arrows }};
10 | {% endfor %}{% endfor %}
11 |
--------------------------------------------------------------------------------
/cli/graph_templates/tail.html:
--------------------------------------------------------------------------------
1 | }
2 |
--------------------------------------------------------------------------------
/cli/tests/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/cli/tests/__init__.py
--------------------------------------------------------------------------------
/cli/tests/entry_points/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/cli/tests/entry_points/__init__.py
--------------------------------------------------------------------------------
/cli/tests/entry_points/conftest.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from peewee import SqliteDatabase
3 |
4 | from common.entities import DB
5 |
6 |
7 | @pytest.fixture
8 | def test_db():
9 | DB.initialize(SqliteDatabase(":memory:", pragmas={"foreign_keys": 1}))
10 | yield DB
11 | DB.obj = None
12 |
--------------------------------------------------------------------------------
/cli/tests/test_imports.py:
--------------------------------------------------------------------------------
1 | import pytest
2 |
3 | from cli import modules
4 |
5 |
6 | @pytest.mark.unit
7 | @pytest.mark.parametrize("module", modules)
8 | def test_entry_point_import(module):
9 | """Validates that all specified entry points can be imported without errors."""
10 | try:
11 | __import__(module)
12 | except ImportError as e:
13 | raise AssertionError(f"Unable to import entry point: {module}") from e
14 | except Exception as e:
15 | raise AssertionError(f"Unexpected error importing entry point: {module}") from e
16 |
--------------------------------------------------------------------------------
/common/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/common/__init__.py
--------------------------------------------------------------------------------
/common/actions/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/common/actions/__init__.py
--------------------------------------------------------------------------------
/common/api/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/common/api/__init__.py
--------------------------------------------------------------------------------
/common/api/flask_ext/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/common/api/flask_ext/__init__.py
--------------------------------------------------------------------------------
/common/api/flask_ext/authentication/__init__.py:
--------------------------------------------------------------------------------
1 | __all__ = ["ServiceAccountAuth", "JWTAuth"]
2 |
3 | from .jwt_plugin import JWTAuth
4 | from .service_account_key_plugin import ServiceAccountAuth
5 |
--------------------------------------------------------------------------------
/common/auth/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/common/auth/__init__.py
--------------------------------------------------------------------------------
/common/auth/keys/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/common/auth/keys/__init__.py
--------------------------------------------------------------------------------
/common/auth/keys/settings.py:
--------------------------------------------------------------------------------
1 | HASH_ITERATIONS: int = 390_000
2 | """
3 | Default iterations for hashing a supplied password.
4 |
5 | This number is picked somewhat at random. It needs to be significantly large to yield an appropriate work factor
6 | but the exact value doesn't matter.
7 | """
8 |
9 | DEFAULT_EXPIRY_DAYS: int = 365
10 | """Default length of time an API key is valid; defaults to 1 year (365 days)."""
11 |
--------------------------------------------------------------------------------
/common/constants/__init__.py:
--------------------------------------------------------------------------------
1 | from .defaults import *
2 | from .email_templates import *
3 | from .peewee import *
4 | from .rbac import *
5 | from .schema_limits import *
6 | from .schema_validation import *
7 | from .validation_messages import *
8 |
--------------------------------------------------------------------------------
/common/constants/defaults.py:
--------------------------------------------------------------------------------
1 | import zoneinfo
2 |
3 | SCHEDULE_START_CRON_TIMEZONE: zoneinfo.ZoneInfo = zoneinfo.ZoneInfo("UTC")
4 |
--------------------------------------------------------------------------------
/common/constants/peewee.py:
--------------------------------------------------------------------------------
1 | BATCH_SIZE: int = 100
2 | """Default batch size for large updates."""
3 |
--------------------------------------------------------------------------------
/common/constants/rbac.py:
--------------------------------------------------------------------------------
1 | ADMIN_ROLE = "ADMIN"
2 | """The name given to the administrative role."""
3 |
--------------------------------------------------------------------------------
/common/constants/schema_validation.py:
--------------------------------------------------------------------------------
1 | EXTENDED_ALPHANUMERIC_REGEX = r"^(?!_)[\w ]*(? Optional[ForeignKeyField]:
17 | return None
18 |
--------------------------------------------------------------------------------
/common/entities/dataset.py:
--------------------------------------------------------------------------------
1 | __all__ = ["Dataset"]
2 |
3 |
4 | from .base_entity import BaseModel
5 | from .component import ComponentType
6 | from .component_meta import SimpleComponentMeta
7 |
8 |
9 | class Dataset(BaseModel, metaclass=SimpleComponentMeta):
10 | """Representation of a dataset component in the application."""
11 |
12 | component_type = ComponentType.DATASET.name
13 |
--------------------------------------------------------------------------------
/common/entities/organization.py:
--------------------------------------------------------------------------------
1 | __all__ = ["Organization"]
2 |
3 | from peewee import CharField, ForeignKeyField
4 |
5 | from .base_entity import AuditEntityMixin, BaseEntity
6 | from .company import Company
7 |
8 |
9 | class Organization(BaseEntity, AuditEntityMixin):
10 | """Second tier of hierarchy -- representing a subsection of the Company"""
11 |
12 | name = CharField(null=False)
13 | description = CharField(null=True)
14 | company = ForeignKeyField(Company, backref="organizations", on_delete="CASCADE", null=False, index=True)
15 |
16 | class Meta:
17 | # Multi-column indexes
18 | indexes = (
19 | # Unique index across company + name
20 | (("company", "name"), True),
21 | )
22 |
--------------------------------------------------------------------------------
/common/entities/pipeline.py:
--------------------------------------------------------------------------------
1 | __all__ = ["Pipeline"]
2 |
3 |
4 | from .base_entity import BaseModel
5 | from .component import ComponentType
6 | from .component_meta import SimpleComponentMeta
7 |
8 |
9 | class Pipeline(BaseModel, metaclass=SimpleComponentMeta):
10 | """Representation of a batch-pipeline component in the application."""
11 |
12 | component_type = ComponentType.BATCH_PIPELINE.name
13 |
--------------------------------------------------------------------------------
/common/entities/server.py:
--------------------------------------------------------------------------------
1 | __all__ = ["Server"]
2 |
3 |
4 | from .base_entity import BaseModel
5 | from .component import ComponentType
6 | from .component_meta import SimpleComponentMeta
7 |
8 |
9 | class Server(BaseModel, metaclass=SimpleComponentMeta):
10 | """Representation of a server component in the application."""
11 |
12 | component_type = ComponentType.SERVER.name
13 |
--------------------------------------------------------------------------------
/common/entities/streaming_pipeline.py:
--------------------------------------------------------------------------------
1 | __all__ = ["StreamingPipeline"]
2 |
3 |
4 | from .base_entity import BaseModel
5 | from .component import ComponentType
6 | from .component_meta import SimpleComponentMeta
7 |
8 |
9 | class StreamingPipeline(BaseModel, metaclass=SimpleComponentMeta):
10 | """Representation of a streaming-pipeline component in the application."""
11 |
12 | component_type = ComponentType.STREAMING_PIPELINE.name
13 |
--------------------------------------------------------------------------------
/common/entities/upcoming_instance.py:
--------------------------------------------------------------------------------
1 | __all__ = ["UpcomingInstance"]
2 | from dataclasses import dataclass
3 | from datetime import datetime
4 | from typing import Optional
5 |
6 | from common.entities.journey import Journey
7 |
8 |
9 | @dataclass
10 | class UpcomingInstance:
11 | journey: Journey
12 | expected_start_time: Optional[datetime] = None
13 | expected_end_time: Optional[datetime] = None
14 |
--------------------------------------------------------------------------------
/common/entity_services/__init__.py:
--------------------------------------------------------------------------------
1 | from .company_service import *
2 | from .component_service import *
3 | from .event_service import *
4 | from .instance_service import *
5 | from .journey_service import *
6 | from .organization_service import *
7 | from .pipeline_service import *
8 | from .project_service import *
9 | from .run_service import *
10 | from .sa_key_service import *
11 | from .test_outcome_service import *
12 | from .upcoming_instance_service import *
13 | from .user_service import *
14 |
--------------------------------------------------------------------------------
/common/entity_services/agent_service.py:
--------------------------------------------------------------------------------
1 | __all__ = ["get_agents_with_rules"]
2 |
3 | from common.entities import Agent
4 | from common.entity_services.helpers import ListRules
5 | from common.entity_services.helpers.list_rules import Page
6 |
7 |
8 | def get_agents_with_rules(project_id: str, rules: ListRules) -> Page[Agent]:
9 | base_query = Agent.project == project_id
10 | if rules.search is not None:
11 | search_query = (Agent.key ** f"%{rules.search}%") | (Agent.tool ** f"%{rules.search}%")
12 | base_query &= search_query
13 | query = Agent.select().where(base_query)
14 | results = query.order_by(rules.order_by_field(Agent.key)).paginate(rules.page, rules.count)
15 | return Page[Agent](results=results, total=query.count())
16 |
--------------------------------------------------------------------------------
/common/entity_services/helpers/__init__.py:
--------------------------------------------------------------------------------
1 | from .filter_rules import *
2 | from .list_rules import *
3 |
--------------------------------------------------------------------------------
/common/entity_services/organization_service.py:
--------------------------------------------------------------------------------
1 | __all__ = ["OrganizationService"]
2 |
3 | from common.entities import Project
4 | from common.entity_services.helpers import ListRules
5 | from common.entity_services.helpers.list_rules import Page
6 |
7 |
8 | class OrganizationService:
9 | @staticmethod
10 | def get_projects_with_rules(org_id: str, rules: ListRules) -> Page[Project]:
11 | query = Project.organization == org_id
12 |
13 | if rules.search is not None:
14 | query &= Project.name ** f"%{rules.search}%"
15 |
16 | results = Project.select().where(query)
17 | return Page[Project].get_paginated_results(results, Project.name, rules)
18 |
--------------------------------------------------------------------------------
/common/entity_services/pipeline_service.py:
--------------------------------------------------------------------------------
1 | __all__ = ["PipelineService"]
2 | import logging
3 | from typing import Optional
4 |
5 | from common.entities import Pipeline
6 |
7 | LOG = logging.getLogger(__name__)
8 |
9 |
10 | class PipelineService:
11 | @staticmethod
12 | def get_by_key_and_project(pipeline_key: Optional[str], project_id: str) -> Pipeline:
13 | pipeline: Pipeline = Pipeline.get(Pipeline.key == pipeline_key, Pipeline.project == project_id)
14 | return pipeline
15 |
--------------------------------------------------------------------------------
/common/entity_services/sa_key_service.py:
--------------------------------------------------------------------------------
1 | from common.entities import Project, ServiceAccountKey
2 | from common.entity_services.helpers import ListRules, Page
3 |
4 |
5 | class ServiceAccountKeyService:
6 | @staticmethod
7 | def list_with_rules(*, project: Project, rules: ListRules) -> Page[ServiceAccountKey]:
8 | query = ServiceAccountKey.project == project
9 | if rules.search is not None:
10 | query &= (ServiceAccountKey.name ** f"%{rules.search}%") | (
11 | ServiceAccountKey.description ** f"%{rules.search}%"
12 | )
13 | results = ServiceAccountKey.select().where(query)
14 | return Page[ServiceAccountKey].get_paginated_results(results, ServiceAccountKey.name, rules)
15 |
--------------------------------------------------------------------------------
/common/entity_services/user_service.py:
--------------------------------------------------------------------------------
1 | from typing import Optional
2 |
3 | from common.entities import User
4 | from common.entity_services.helpers import ListRules, Page
5 |
6 |
7 | class UserService:
8 | @staticmethod
9 | def list_with_rules(
10 | rules: ListRules, company_id: Optional[str] = None, name_filter: Optional[str] = None
11 | ) -> Page[User]:
12 | query = User.select()
13 | if company_id:
14 | query = query.where(User.primary_company_id == company_id)
15 | if name_filter:
16 | query = query.where(User.name.contains(name_filter))
17 | return Page[User].get_paginated_results(query, User.name, rules)
18 |
--------------------------------------------------------------------------------
/common/events/__init__.py:
--------------------------------------------------------------------------------
1 | from .converters import USER_EVENT_TYPES, to_v1, to_v2 # noqa: F401
2 | from .enums import *
3 | from .event_handler import *
4 | from .v1.event import Event # noqa: F401
5 | from .v2.base import EventV2 # noqa: F401
6 |
--------------------------------------------------------------------------------
/common/events/enums.py:
--------------------------------------------------------------------------------
1 | __all__ = ["ScheduleType"]
2 |
3 | from enum import Enum
4 |
5 |
6 | class ScheduleType(Enum):
7 | BATCH_START_TIME = "BATCH_START_TIME"
8 | BATCH_START_TIME_MARGIN = "BATCH_START_TIME_MARGIN"
9 | BATCH_END_TIME = "BATCH_END_TIME"
10 | DATASET_ARRIVAL_MARGIN = "DATASET_ARRIVAL_MARGIN"
11 |
12 |
13 | class EventSources(Enum):
14 | API = "API"
15 | USER = "USER"
16 | SCHEDULER = "SCHEDULER"
17 | RULES_ENGINE = "RULES_ENGINE"
18 | # This last one should be considered a bug if seen in the wild. But it can be used as a dumb-default for tracing.
19 | UNKNOWN = "UNKNOWN"
20 |
--------------------------------------------------------------------------------
/common/events/internal/__init__.py:
--------------------------------------------------------------------------------
1 | from .alert import *
2 | from .scheduled_event import *
3 | from .scheduled_instance import *
4 | from .system import *
5 |
--------------------------------------------------------------------------------
/common/events/internal/scheduled_instance.py:
--------------------------------------------------------------------------------
1 | __all__ = [
2 | "ScheduledInstance",
3 | ]
4 |
5 | from dataclasses import dataclass
6 | from datetime import datetime
7 | from uuid import UUID
8 |
9 | from common.entities import InstanceRuleAction
10 | from common.events.base import ProjectMixin
11 |
12 |
13 | @dataclass(kw_only=True)
14 | class ScheduledInstance(ProjectMixin):
15 | journey_id: UUID
16 | instance_rule_id: UUID
17 | instance_rule_action: InstanceRuleAction
18 | timestamp: datetime
19 |
--------------------------------------------------------------------------------
/common/events/internal/system.py:
--------------------------------------------------------------------------------
1 | __all__ = ["AgentStatusChangeEvent"]
2 |
3 | from datetime import datetime
4 | from dataclasses import dataclass
5 | from uuid import UUID
6 |
7 | from common.entities.agent import AgentStatus
8 | from common.events.base import EventBaseMixin, ProjectMixin
9 |
10 |
11 | @dataclass(kw_only=True)
12 | class AgentStatusChangeEvent(EventBaseMixin, ProjectMixin):
13 | agent_id: UUID
14 | agent_key: str
15 | agent_tool: str
16 | previous_status: AgentStatus
17 | current_status: AgentStatus
18 | latest_heartbeat: datetime
19 | latest_event_timestamp: datetime
20 |
--------------------------------------------------------------------------------
/common/events/v2/__init__.py:
--------------------------------------------------------------------------------
1 | from .base import *
2 | from .batch_pipeline_status import *
3 | from .component_data import *
4 | from .dataset_operation import *
5 | from .message_log import *
6 | from .metric_log import *
7 | from .test_outcomes import *
8 | from .testgen import *
9 |
10 | ALL_API_EVENT_SCHEMAS = [
11 | BatchPipelineStatusSchema,
12 | DatasetOperationSchema,
13 | EventResponseSchema,
14 | MessageLogSchema,
15 | MetricLogSchema,
16 | TestOutcomesSchema,
17 | ]
18 |
--------------------------------------------------------------------------------
/common/events/v2/helpers.py:
--------------------------------------------------------------------------------
1 | from common.entities import ApiEventType
2 |
3 | from .batch_pipeline_status import BatchPipelineStatusSchema
4 | from .dataset_operation import DatasetOperationSchema
5 | from .message_log import MessageLogSchema
6 | from .metric_log import MetricLogSchema
7 | from .test_outcomes import TestOutcomesSchema
8 |
9 | EVENT_TYPE_SCHEMAS = {
10 | ApiEventType.BATCH_PIPELINE_STATUS: BatchPipelineStatusSchema,
11 | ApiEventType.DATASET_OPERATION: DatasetOperationSchema,
12 | ApiEventType.MESSAGE_LOG: MessageLogSchema,
13 | ApiEventType.METRIC_LOG: MetricLogSchema,
14 | ApiEventType.TEST_OUTCOMES: TestOutcomesSchema,
15 | }
16 |
--------------------------------------------------------------------------------
/common/exceptions/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/common/exceptions/__init__.py
--------------------------------------------------------------------------------
/common/exceptions/service.py:
--------------------------------------------------------------------------------
1 | class ServiceException(Exception):
2 | def __init__(self, msg: str) -> None:
3 | self.message = msg
4 | super().__init__(self.message)
5 |
6 |
7 | class MultipleActionsFound(ServiceException):
8 | pass
9 |
--------------------------------------------------------------------------------
/common/kafka/__init__.py:
--------------------------------------------------------------------------------
1 | from .consumer import *
2 | from .errors import *
3 | from .message import *
4 | from .producer import *
5 | from .settings import *
6 | from .topic import *
7 |
--------------------------------------------------------------------------------
/common/kafka/message.py:
--------------------------------------------------------------------------------
1 | __all__ = ["KafkaMessage"]
2 | from dataclasses import dataclass
3 | from typing import Generic, Optional, TypeVar
4 |
5 | T = TypeVar("T")
6 |
7 |
8 | @dataclass(frozen=True, kw_only=True)
9 | class KafkaMessage(Generic[T]):
10 | """
11 | A generic Kafka message
12 |
13 | It is mainly used to convey payload and metadata info to consumers. The
14 | payload type is determined by the topic.
15 | """
16 |
17 | payload: T
18 | topic: str
19 | partition: int
20 | offset: int
21 | headers: dict
22 | key: Optional[str] = None
23 |
--------------------------------------------------------------------------------
/common/kubernetes/__init__.py:
--------------------------------------------------------------------------------
1 | from .readiness_probe import *
2 |
--------------------------------------------------------------------------------
/common/logging/__init__.py:
--------------------------------------------------------------------------------
1 | from .json_logging import *
2 |
--------------------------------------------------------------------------------
/common/peewee_extensions/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/common/peewee_extensions/__init__.py
--------------------------------------------------------------------------------
/common/peewee_extensions/templates/model.toml:
--------------------------------------------------------------------------------
1 | table_name = "{{ table_name }}"
2 | fixture_id = "{{ fixture_id }}"{% if requires %}
3 | requires_id = "{{ requires_id }}"{% endif %}
4 | {% for row in rows %}
5 | [[row]]
6 | {% for field, data in row.items() %}{% if data["value"] is not none %}{{ field }} = {{ data|toml_value }}
7 | {% endif %}{% endfor %}{% endfor %}
8 |
--------------------------------------------------------------------------------
/common/predicate_engine/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/common/predicate_engine/__init__.py
--------------------------------------------------------------------------------
/common/predicate_engine/exceptions.py:
--------------------------------------------------------------------------------
1 | class InvalidRuleData(ValueError):
2 | """Raised when attempting to compile rule data into a R object."""
3 |
--------------------------------------------------------------------------------
/common/predicate_engine/schemas/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/common/predicate_engine/schemas/__init__.py
--------------------------------------------------------------------------------
/common/schemas/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/common/schemas/__init__.py
--------------------------------------------------------------------------------
/common/schemas/fields/__init__.py:
--------------------------------------------------------------------------------
1 | from .cron_expr_str import *
2 | from .enum_str import *
3 | from .normalized_str import *
4 | from .zoneinfo import *
5 |
--------------------------------------------------------------------------------
/common/schemas/validators/__init__.py:
--------------------------------------------------------------------------------
1 | from .not_empty import *
2 | from .regexp import *
3 |
--------------------------------------------------------------------------------
/common/schemas/validators/not_empty.py:
--------------------------------------------------------------------------------
1 | __all__ = ["not_empty"]
2 |
3 | from functools import partial
4 | from collections.abc import Callable
5 |
6 | from marshmallow import validate
7 |
8 | not_empty: Callable = partial(validate.Length, min=1)
9 | """
10 | A lot of times, we just want to validate that some message exists and is non-empty. Field classes such as
11 | Str class do not check the booleanness of a string, nor its length without a validator like this. As for why
12 | It's a partial like this; I thought it'd be more readable considering it's used so many places.
13 | """
14 |
--------------------------------------------------------------------------------
/common/schemas/validators/regexp.py:
--------------------------------------------------------------------------------
1 | __all__ = ["IsRegexp"]
2 |
3 | import re
4 | from typing import Optional
5 |
6 | from marshmallow import ValidationError
7 | from marshmallow.validate import Validator
8 |
9 |
10 | class IsRegexp(Validator):
11 | """
12 | Validates the input string is a regular expression.
13 | """
14 |
15 | message_invalid = "Invalid regular expression"
16 |
17 | def __init__(self, *, error: Optional[str] = None) -> None:
18 | self.error: str = error or self.message_invalid
19 |
20 | def __call__(self, value: str) -> str:
21 | try:
22 | re.compile(value)
23 | except Exception as e:
24 | raise ValidationError(self.error.format(input=value)) from e
25 | return value
26 |
--------------------------------------------------------------------------------
/common/sentinel.py:
--------------------------------------------------------------------------------
1 | from enum import Enum
2 |
3 |
4 | class Sentinel(Enum):
5 | """Sentinel object (as Enum for type checking unless PEP-661 is ever approved)."""
6 |
7 | _ = object()
8 |
9 |
10 | SENTINEL = Sentinel._
11 |
--------------------------------------------------------------------------------
/common/tests/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/common/tests/__init__.py
--------------------------------------------------------------------------------
/common/tests/fake_models/__init__.py:
--------------------------------------------------------------------------------
1 | """Fake models module for testing."""
2 |
--------------------------------------------------------------------------------
/common/tests/fake_models/model_a.py:
--------------------------------------------------------------------------------
1 | from peewee import CharField, Model
2 |
3 |
4 | class FakeModelA(Model):
5 | foo = CharField()
6 | bar = CharField()
7 |
--------------------------------------------------------------------------------
/common/tests/fake_models/model_b.py:
--------------------------------------------------------------------------------
1 | from peewee import CharField, Model
2 |
3 |
4 | class FakeModelB(Model):
5 | fizz = CharField()
6 | buzz = CharField()
7 |
--------------------------------------------------------------------------------
/common/tests/integration/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/common/tests/integration/__init__.py
--------------------------------------------------------------------------------
/common/tests/integration/actions/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/common/tests/integration/actions/__init__.py
--------------------------------------------------------------------------------
/common/tests/integration/actions/test_action_factory.py:
--------------------------------------------------------------------------------
1 | import pytest
2 |
3 | from common.actions.action_factory import ACTION_CLASS_MAP
4 | from common.schemas.action_schemas import ValidActions
5 |
6 |
7 | @pytest.mark.integration
8 | def test_check_all_action_implemented():
9 | # Check that valid actions are represented in the action factory map and vice versa.
10 | assert ACTION_CLASS_MAP.keys() == set(a.name for a in ValidActions)
11 |
--------------------------------------------------------------------------------
/common/tests/integration/api/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/common/tests/integration/api/__init__.py
--------------------------------------------------------------------------------
/common/tests/integration/auth/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/common/tests/integration/auth/__init__.py
--------------------------------------------------------------------------------
/common/tests/integration/auth/conftest.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from peewee import SqliteDatabase
3 |
4 | from common.entities import ALL_MODELS, DB
5 |
6 |
7 | @pytest.fixture
8 | def test_db():
9 | DB.initialize(SqliteDatabase(":memory:", pragmas={"foreign_keys": 1}))
10 | yield DB
11 |
12 |
13 | @pytest.fixture(autouse=True)
14 | def test_base(test_db):
15 | test_db.create_tables(ALL_MODELS)
16 | yield
17 | test_db.drop_tables(ALL_MODELS)
18 | test_db.close()
19 |
--------------------------------------------------------------------------------
/common/tests/integration/email/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/common/tests/integration/email/__init__.py
--------------------------------------------------------------------------------
/common/tests/integration/entities/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/common/tests/integration/entities/__init__.py
--------------------------------------------------------------------------------
/common/tests/integration/entities/test_dataset_operation.py:
--------------------------------------------------------------------------------
1 | from datetime import datetime
2 |
3 | import pytest
4 |
5 | from common.entities import DatasetOperation, DatasetOperationType
6 |
7 |
8 | @pytest.mark.integration
9 | def test_dataset_operation_create(dataset, instance_set):
10 | DatasetOperation.create(
11 | dataset=dataset,
12 | instance_set=instance_set,
13 | operation=DatasetOperationType.WRITE,
14 | operation_time=datetime.utcnow(),
15 | )
16 |
--------------------------------------------------------------------------------
/common/tests/integration/entities/test_rule.py:
--------------------------------------------------------------------------------
1 | import pytest
2 |
3 | from common.entities import Rule
4 |
5 |
6 | @pytest.mark.integration
7 | def test_rule_create(action, pipeline, journey):
8 | Rule.create(
9 | name="test rule",
10 | journey=journey,
11 | rule_schema="fake schema",
12 | rule_data="fake data",
13 | action=action,
14 | component=pipeline,
15 | )
16 |
17 |
18 | @pytest.mark.integration
19 | def test_rule_defaults(action, journey):
20 | rule = Rule.create(
21 | name="test rule", rule_schema="fake schema", rule_data="fake data", action=action, journey=journey
22 | )
23 | assert rule.action_args == {}
24 |
--------------------------------------------------------------------------------
/common/tests/integration/entities/test_schedule.py:
--------------------------------------------------------------------------------
1 | import pytest
2 |
3 | from common.entities import Schedule, ScheduleExpectation
4 |
5 |
6 | @pytest.mark.integration
7 | def test_schedule_create(pipeline):
8 | Schedule.create(
9 | component=pipeline,
10 | description="Some cool schedule",
11 | schedule="25 */2 * * *",
12 | timezone="EST",
13 | expectation=ScheduleExpectation.BATCH_PIPELINE_START_TIME.value,
14 | margin=120,
15 | )
16 |
--------------------------------------------------------------------------------
/common/tests/integration/entities/test_user.py:
--------------------------------------------------------------------------------
1 | import pytest
2 |
3 | from common.entities import Company, Role, User, UserRole
4 |
5 |
6 | @pytest.mark.integration
7 | def test_user_has_role_on():
8 | company = Company.create(name="Foo")
9 | user = User.create(name="Not Max", email="bar", foreign_user_id="def", primary_company=company)
10 | role = Role.create(name="test-user-role")
11 | UserRole.create(user=user, role=role)
12 | assert user.has_role("test-user-role") is True
13 | assert user.has_role("this-role-no-existy") is False
14 |
--------------------------------------------------------------------------------
/common/tests/integration/entity_services/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/common/tests/integration/entity_services/__init__.py
--------------------------------------------------------------------------------
/common/tests/integration/events/conftest.py:
--------------------------------------------------------------------------------
1 | from testlib.fixtures.v1_events import *
2 |
--------------------------------------------------------------------------------
/common/tests/integration/flask_ext/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/common/tests/integration/flask_ext/__init__.py
--------------------------------------------------------------------------------
/common/tests/integration/peewee_extensions/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/common/tests/integration/peewee_extensions/__init__.py
--------------------------------------------------------------------------------
/common/tests/integration/peewee_extensions/bad_fixtures/company.toml:
--------------------------------------------------------------------------------
1 | table_name = "company"
2 | # NOTE: This is a cyclic dependency.
3 | fixture_id = "9da3a73e-ac41-4ef3-9527-0bee2cb1232d"
4 | requires_id = "7030ed67-1fdd-4d7e-8ca0-f758599600b6"
5 |
6 | [[row]]
7 | id = "3f49acf2-327d-4b20-bf24-6801ea9013ed"
8 | active = true
9 | created_on = "2022-06-22T17:46:36.479602+00:00"
10 | name = "LiteralKitchen"
11 |
--------------------------------------------------------------------------------
/common/tests/integration/peewee_extensions/bad_fixtures/organization.toml:
--------------------------------------------------------------------------------
1 | table_name = "organization"
2 | fixture_id = "7030ed67-1fdd-4d7e-8ca0-f758599600b6"
3 | requires_id = "9da3a73e-ac41-4ef3-9527-0bee2cb1232d"
4 |
5 |
6 | [[row]]
7 | id = "ea8af577-d714-4804-822a-f002434a2b1a"
8 | created_on = "2022-06-22T17:46:14.097997+00:00"
9 | name = "default"
10 | description = """
11 | This is a cool place to be I guess."""
12 | company = "3f49acf2-327d-4b20-bf24-6801ea9013ed"
13 | active = true
14 |
--------------------------------------------------------------------------------
/common/tests/integration/peewee_extensions/conftest.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from peewee import SqliteDatabase
3 |
4 | from common.entities import ALL_MODELS, DB
5 |
6 |
7 | @pytest.fixture
8 | def test_db_base():
9 | DB.initialize(SqliteDatabase(":memory:", pragmas={"foreign_keys": 1}))
10 | yield DB
11 | DB.obj = None
12 |
13 |
14 | @pytest.fixture
15 | def test_db(test_db_base):
16 | test_db_base.create_tables(ALL_MODELS)
17 | yield
18 | test_db_base.drop_tables(ALL_MODELS)
19 | test_db_base.close()
20 |
--------------------------------------------------------------------------------
/common/tests/integration/peewee_extensions/fixtures/company.toml:
--------------------------------------------------------------------------------
1 | table_name = "company"
2 | fixture_id = "9da3a73e-ac41-4ef3-9527-0bee2cb1232d"
3 |
4 | [[row]]
5 | id = "3f49acf2-327d-4b20-bf24-6801ea9013ed"
6 | created_on = 1672179122156235
7 | name = "LiteralKitchen"
8 |
--------------------------------------------------------------------------------
/common/tests/integration/peewee_extensions/fixtures/organization.toml:
--------------------------------------------------------------------------------
1 | table_name = "organization"
2 | fixture_id = "7030ed67-1fdd-4d7e-8ca0-f758599600b6"
3 | requires_id = "9da3a73e-ac41-4ef3-9527-0bee2cb1232d"
4 |
5 | [[row]]
6 | id = "a80e6e65-e268-447b-aaef-68057915a7ef"
7 | created_on = 1672179122156235
8 | name = "default"
9 | description = """
10 | This is a cool place to be I guess."""
11 | company = "3f49acf2-327d-4b20-bf24-6801ea9013ed"
12 |
--------------------------------------------------------------------------------
/common/tests/integration/peewee_extensions/fixtures/project.toml:
--------------------------------------------------------------------------------
1 | table_name = "project"
2 | fixture_id = "70fe8951-d433-426d-8c08-5ca96117f740"
3 | requires_id = "7030ed67-1fdd-4d7e-8ca0-f758599600b6"
4 |
5 | [[row]]
6 | id = "9fbee19e-5319-4366-b4b8-b3c589525297"
7 | active = true
8 | created_on = 1672179122156235
9 | name = "default"
10 | organization = "a80e6e65-e268-447b-aaef-68057915a7ef"
11 |
--------------------------------------------------------------------------------
/common/tests/integration/peewee_extensions/fixtures/service-account-key.toml:
--------------------------------------------------------------------------------
1 | table_name = "service_account_key"
2 | fixture_id = "bed70422-32de-40f4-a781-555e4238e11d"
3 | requires_id = "70fe8951-d433-426d-8c08-5ca96117f740"
4 |
5 | [[row]]
6 | digest = "gmuIsKVv1TfN/hU1TvS+/fFZXs/e1HCEeu+0x6pcF3l8MzkwMDAwfDkzNTYxMTQxLTZmZjgtNGRiNi1hMjY4LTk4ZDA4MzczYzQzYQ=="
7 | expiry = 1690981384890272
8 | id = "c780843a-ea7d-47da-8aaf-d3eed3e53e9b"
9 | project = "9fbee19e-5319-4366-b4b8-b3c589525297"
10 | allowed_services = '["EVENTS_API"]'
11 | name = "Default"
12 |
--------------------------------------------------------------------------------
/common/tests/unit/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/common/tests/unit/__init__.py
--------------------------------------------------------------------------------
/common/tests/unit/actions/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/common/tests/unit/actions/__init__.py
--------------------------------------------------------------------------------
/common/tests/unit/api/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/common/tests/unit/api/__init__.py
--------------------------------------------------------------------------------
/common/tests/unit/auth/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/common/tests/unit/auth/__init__.py
--------------------------------------------------------------------------------
/common/tests/unit/constants/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/common/tests/unit/constants/__init__.py
--------------------------------------------------------------------------------
/common/tests/unit/constants/test_schema_validation.py:
--------------------------------------------------------------------------------
1 | import re
2 |
3 | import pytest
4 |
5 | from common.constants import EXTENDED_ALPHANUMERIC_REGEX
6 |
7 |
8 | @pytest.mark.unit
9 | @pytest.mark.parametrize("value", ("", " ", "z", "åêà", "aA1", "b B", " c ", "d_D", "123_abc 456 EDF"))
10 | def test_extended_alphanumeric_regex_matching(value):
11 | assert re.match(EXTENDED_ALPHANUMERIC_REGEX, value)
12 |
13 |
14 | @pytest.mark.unit
15 | @pytest.mark.parametrize("value", ("!", "_", "_a", "b_c-d"))
16 | def test_extended_alphanumeric_regex_not_matching(value):
17 | assert not re.match(EXTENDED_ALPHANUMERIC_REGEX, value)
18 |
--------------------------------------------------------------------------------
/common/tests/unit/email/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/common/tests/unit/email/__init__.py
--------------------------------------------------------------------------------
/common/tests/unit/entities/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/common/tests/unit/entities/__init__.py
--------------------------------------------------------------------------------
/common/tests/unit/entity_services/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/common/tests/unit/entity_services/__init__.py
--------------------------------------------------------------------------------
/common/tests/unit/entity_services/helpers/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/common/tests/unit/entity_services/helpers/__init__.py
--------------------------------------------------------------------------------
/common/tests/unit/events/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/common/tests/unit/events/__init__.py
--------------------------------------------------------------------------------
/common/tests/unit/events/v1/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/common/tests/unit/events/v1/__init__.py
--------------------------------------------------------------------------------
/common/tests/unit/events/v1/conftest.py:
--------------------------------------------------------------------------------
1 | from testlib.fixtures.v1_events import *
2 |
--------------------------------------------------------------------------------
/common/tests/unit/events/v1/test_event_schemas.py:
--------------------------------------------------------------------------------
1 | import json
2 |
3 | import pytest
4 |
5 | from common.events.v1 import EventSchema
6 |
7 |
8 | @pytest.mark.unit
9 | def test_decode_bytes_with_dict(event_data):
10 | EventSchema().load(event_data)
11 |
12 |
13 | @pytest.mark.unit
14 | def test_decode_bytes_with_bytes(event_data):
15 | EventSchema().load(json.dumps(event_data).encode("utf-8"))
16 |
--------------------------------------------------------------------------------
/common/tests/unit/flask_ext/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/common/tests/unit/flask_ext/__init__.py
--------------------------------------------------------------------------------
/common/tests/unit/flask_ext/conftest.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/common/tests/unit/flask_ext/conftest.py
--------------------------------------------------------------------------------
/common/tests/unit/flask_ext/test_cors.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from flask import Response
3 |
4 | from common.api.flask_ext.cors import CORS, CORS_HEADERS
5 |
6 | CORS_HEADER_TUPLE: tuple[str, ...] = tuple(CORS_HEADERS.keys())
7 |
8 |
9 | @pytest.mark.unit
10 | def test_headers_added():
11 | response = Response()
12 | CORS.set_cors_headers(response)
13 | for header_name in CORS_HEADER_TUPLE:
14 | assert header_name in response.headers
15 |
--------------------------------------------------------------------------------
/common/tests/unit/kafka/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/common/tests/unit/kafka/__init__.py
--------------------------------------------------------------------------------
/common/tests/unit/kubernetes/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/common/tests/unit/kubernetes/__init__.py
--------------------------------------------------------------------------------
/common/tests/unit/logging/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/common/tests/unit/logging/__init__.py
--------------------------------------------------------------------------------
/common/tests/unit/peewee_extensions/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/common/tests/unit/peewee_extensions/__init__.py
--------------------------------------------------------------------------------
/common/tests/unit/predicate_engine/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/common/tests/unit/predicate_engine/__init__.py
--------------------------------------------------------------------------------
/common/tests/unit/schemas/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/common/tests/unit/schemas/__init__.py
--------------------------------------------------------------------------------
/common/tests/unit/schemas/fields/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/common/tests/unit/schemas/fields/__init__.py
--------------------------------------------------------------------------------
/common/tests/unit/schemas/validators/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/common/tests/unit/schemas/validators/__init__.py
--------------------------------------------------------------------------------
/common/typing.py:
--------------------------------------------------------------------------------
1 | """A module for custom type definitions."""
2 |
3 | JWT_CLAIMS = dict[str, object]
4 | """Type for decoded JWT token."""
5 |
--------------------------------------------------------------------------------
/common/user_strings/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/common/user_strings/__init__.py
--------------------------------------------------------------------------------
/conf/defaults.py:
--------------------------------------------------------------------------------
1 | RULE_REFRESH_SECONDS: int = 30
2 | """Number of seconds to cache rules in rules engine"""
3 |
4 |
5 | MIGRATIONS_SRC_PATH = "/dk/lib/migrations"
6 | """Yoyo migrations source folder."""
7 |
8 | AGENT_STATUS_CHECK_DEFAULT_INTERVAL_SECONDS: int = 300
9 | """Default polling internal for Agent status changes."""
10 |
11 | AGENT_STATUS_CHECK_UNHEALTHY_FACTOR: float = 2
12 | """Multiplier factor to consider an Agent unhealthy, based on the checking interval."""
13 |
14 | AGENT_STATUS_CHECK_OFFLINE_FACTOR: float = 4
15 | """Multiplier factor to consider an Agent offline, based on the checking interval."""
16 |
--------------------------------------------------------------------------------
/conf/local.py:
--------------------------------------------------------------------------------
1 | from pathlib import Path
2 |
3 | from peewee import SqliteDatabase
4 |
5 | PROJECT_ROOT = Path(__file__).parent.parent
6 |
7 | DATABASE: dict[str, object] = {
8 | "name": PROJECT_ROOT.joinpath("test.db"),
9 | "engine": SqliteDatabase,
10 | "pragmas": {
11 | "journal_mode": "wal",
12 | "cache_size": -1, # 10000 pages, or ~40MB
13 | "foreign_keys": 1, # Enforce foreign-key constraints
14 | "ignore_check_constraints": 0, # enforce CHECK constraints
15 | "case_sensitive_like": True, # Case sensitive queries
16 | },
17 | }
18 | """Settings for a local sqlite database running locally."""
19 |
--------------------------------------------------------------------------------
/conf/test.py:
--------------------------------------------------------------------------------
1 | from peewee import SqliteDatabase
2 |
3 | DATABASE: dict[str, object] = {
4 | "name": "file:cachedb?mode=memory&cache=shared",
5 | "engine": SqliteDatabase,
6 | "pragmas": {"foreign_keys": 1},
7 | "uri": True,
8 | }
9 | """Configures an in-memory database with a shared cache for testing."""
10 |
11 | KAFKA_CONNECTION_PARAMS: dict[str, str] = {}
12 | """Empty Kafka connect parameters to please unit tests."""
13 |
14 | SMTP: dict[str, object] = {
15 | "username": "",
16 | "password": "",
17 | "endpoint": "",
18 | "port": 25,
19 | "from_address": "",
20 | }
21 | """Dummy SMTP parameters to please unit tests."""
22 |
--------------------------------------------------------------------------------
/conftest.py:
--------------------------------------------------------------------------------
1 | import os
2 |
3 | import pytest
4 |
5 |
6 | def pytest_configure(config: pytest.Config) -> None:
7 | os.environ["OBSERVABILITY_CONFIG"] = "test"
8 |
--------------------------------------------------------------------------------
/deploy/charts/observability-app/Chart.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v2
2 | name: dataops-observability-app
3 | type: application
4 | appVersion: "2.x.x"
5 | version: "2.2.4"
6 |
7 | description: DataOps Observability
8 | home: https://datakitchen.io
9 | icon: https://cloud.datakitchen.io/assets/image/dk-logo.svg
10 | keywords:
11 | - datakitchen
12 | - dataops
13 | maintainers:
14 | - name: DataKitchen
15 | url: https://datakitchen.io
16 |
--------------------------------------------------------------------------------
/deploy/charts/observability-app/templates/_probes.tpl:
--------------------------------------------------------------------------------
1 | {{/*
2 | Command-based readiness probe
3 | */}}
4 |
5 | {{- define "observability.probes.readiness_cmd" -}}
6 | readinessProbe:
7 | exec:
8 | command:
9 | - /dk/bin/{{ . }}
10 | - --check-ready
11 | # We are not polling this too often and also have a generous timeout because the check ready action waits the ready
12 | # condition to be reached when the service is not ready right away. This allows us to have a tight switch to the
13 | # new pod, potentially reducing the overall deployment time
14 | periodSeconds: 30
15 | timeoutSeconds: 60
16 | {{- end -}}
17 |
--------------------------------------------------------------------------------
/deploy/charts/observability-app/templates/serviceaccount.yaml:
--------------------------------------------------------------------------------
1 | {{- if .Values.serviceAccount.create -}}
2 | apiVersion: v1
3 | kind: ServiceAccount
4 | metadata:
5 | name: {{ include "observability.serviceAccountName" . }}
6 | labels:
7 | {{- include "observability.labels" . | nindent 4 }}
8 | {{- with .Values.serviceAccount.annotations }}
9 | annotations:
10 | {{- toYaml . | nindent 4 }}
11 | {{- end }}
12 | {{- end }}
13 |
--------------------------------------------------------------------------------
/deploy/charts/observability-services/Chart.lock:
--------------------------------------------------------------------------------
1 | dependencies:
2 | - name: kafka
3 | repository: https://charts.bitnami.com/bitnami
4 | version: 20.0.4
5 | - name: mysql
6 | repository: https://charts.bitnami.com/bitnami
7 | version: 9.4.5
8 | digest: sha256:e1ce9f0395b3c90bffe9f3fc989ba4b0deeec7cb0d101d0624523ac44bc89271
9 | generated: "2024-01-17T21:52:57.718202-05:00"
10 |
--------------------------------------------------------------------------------
/deploy/charts/observability-services/Chart.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v2
2 | name: dataops-observability-services
3 | type: application
4 | appVersion: "2.x.x"
5 | version: "2.0.2"
6 |
7 | dependencies:
8 | - name: kafka
9 | version: 20.0.4
10 | repository: https://charts.bitnami.com/bitnami
11 | condition: kafka.enable
12 | - name: mysql
13 | version: 9.4.5
14 | repository: https://charts.bitnami.com/bitnami
15 | condition: mysql.enable
16 |
17 | description: DataOps Observability Supporting Services
18 | home: https://datakitchen.io
19 | icon: https://cloud.datakitchen.io/assets/image/dk-logo.svg
20 | keywords:
21 | - datakitchen
22 | - dataops
23 | maintainers:
24 | - name: DataKitchen
25 | url: https://datakitchen.io
26 |
--------------------------------------------------------------------------------
/deploy/charts_values/values-services-dev.yaml:
--------------------------------------------------------------------------------
1 | kafka:
2 | externalAccess:
3 | enabled: true
4 | service:
5 | type: NodePort
6 | useHostIPs: true
7 | nodePorts: [9092]
8 |
9 | mysql:
10 | primary:
11 | service:
12 | type: NodePort
13 | nodePorts:
14 | mysql: 3306
15 |
--------------------------------------------------------------------------------
/deploy/conf/gunicorn.conf.py:
--------------------------------------------------------------------------------
1 | workers = 2
2 | theads = 16
3 |
--------------------------------------------------------------------------------
/deploy/conf/yoyo.ini:
--------------------------------------------------------------------------------
1 | [DEFAULT]
2 | sources = /dk/lib/migrations
3 | batch_mode = off
4 | verbosity = 2
5 | database = mysql://%(MYSQL_USER)s:%(MYSQL_PASSWORD)s@%(MYSQL_SERVICE_HOST)s:%(MYSQL_SERVICE_PORT)s/%(MYSQL_DATABASE)s
6 |
--------------------------------------------------------------------------------
/deploy/migrations/20240627_01_bgIWR-adding-agent-status-column.py:
--------------------------------------------------------------------------------
1 | """
2 | Adding agent status column
3 | """
4 |
5 | from yoyo import step
6 |
7 | __depends__ = {"20240605_01_vjN7f-initial-schema"}
8 | __transactional__ = False
9 |
10 | steps = [
11 | step(
12 | "ALTER TABLE `agent` ADD COLUMN `status` varchar(20) NOT NULL",
13 | "ALTER TABLE `agent` DROP COLUMN `status`",
14 | ),
15 | ]
16 |
--------------------------------------------------------------------------------
/deploy/migrations/20240627_02_ORQ6B-adding-agent-status-check-config-column.py:
--------------------------------------------------------------------------------
1 | """
2 | Adding agent status check config column
3 | """
4 |
5 | from yoyo import step
6 |
7 | __depends__ = {"20240627_01_bgIWR-adding-agent-status-column"}
8 | __transactional__ = False
9 |
10 | steps = [
11 | step(
12 | "ALTER TABLE `project` ADD COLUMN `agent_status_check_interval` INT NOT NULL",
13 | "ALTER TABLE `project` DROP COLUMN `agent_status_check_interval`",
14 | ),
15 | ]
16 |
--------------------------------------------------------------------------------
/deploy/migrations/20240627_03_4o7tH-agent-status-check-default-values.py:
--------------------------------------------------------------------------------
1 | """
2 | Agent status check default values
3 | """
4 |
5 | from yoyo import step
6 |
7 | __depends__ = {"20240627_02_ORQ6B-adding-agent-status-check-config-column"}
8 |
9 | steps = [
10 | step("UPDATE `project` SET `agent_status_check_interval` = 300"),
11 | step("UPDATE `agent` SET `status` = 'ONLINE'"),
12 | ]
13 |
--------------------------------------------------------------------------------
/deploy/migrations/20240701_01_zRe7i-add-project-alert-config-field.py:
--------------------------------------------------------------------------------
1 | """
2 | Add project alert config field
3 | """
4 |
5 | from yoyo import step
6 |
7 | __depends__ = {"20240627_03_4o7tH-agent-status-check-default-values"}
8 | __transactional__ = False
9 |
10 | steps = [
11 | step(
12 | "ALTER TABLE `project` ADD COLUMN `alert_actions` JSON NOT NULL",
13 | "ALTER TABLE `project` DROP COLUMN `alert_actions`",
14 | )
15 | ]
16 |
--------------------------------------------------------------------------------
/deploy/migrations/20240705_01_37l4A-set-project-alert-config-default.py:
--------------------------------------------------------------------------------
1 | """
2 | Set project alert config default
3 | """
4 |
5 | from yoyo import step
6 |
7 | __depends__ = {"20240701_01_zRe7i-add-project-alert-config-field"}
8 |
9 | steps = [
10 | step("UPDATE `project` SET `alert_actions` = JSON_ARRAY()"),
11 | ]
12 |
--------------------------------------------------------------------------------
/deploy/migrations/20240723_01_K3c3Q-renaming-the-agent-check-interval-column.py:
--------------------------------------------------------------------------------
1 | """
2 | Renaming the agent check interval column
3 | """
4 |
5 | from yoyo import step
6 |
7 | __depends__ = {"20240705_01_37l4A-set-project-alert-config-default"}
8 |
9 | steps = [
10 | step(
11 | "ALTER TABLE `project` RENAME COLUMN `agent_status_check_interval` TO `agent_check_interval`",
12 | "ALTER TABLE `project` RENAME COLUMN `agent_check_interval` TO `agent_status_check_interval`",
13 | ),
14 | ]
15 |
--------------------------------------------------------------------------------
/event_api/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/event_api/__init__.py
--------------------------------------------------------------------------------
/event_api/config/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/event_api/config/__init__.py
--------------------------------------------------------------------------------
/event_api/config/cloud.py:
--------------------------------------------------------------------------------
1 | import os
2 |
3 | # Flask specific settings: https://flask.palletsprojects.com/en/latest/config/#builtin-configuration-values
4 | SECRET_KEY: str = os.environ["EVENTS_KEY_FLASK_SECRET"]
5 | SERVER_NAME: str = os.environ["EVENTS_API_HOSTNAME"]
6 |
--------------------------------------------------------------------------------
/event_api/config/local.py:
--------------------------------------------------------------------------------
1 | from typing import Optional
2 |
3 | # Flask specific settings: https://flask.palletsprojects.com/en/latest/config/#builtin-configuration-values
4 | PROPAGATE_EXCEPTIONS: Optional[bool] = True
5 | SECRET_KEY: str = "NOT_VERY_SECRET"
6 |
--------------------------------------------------------------------------------
/event_api/config/minikube.py:
--------------------------------------------------------------------------------
1 | from typing import Optional
2 |
3 | # Flask specific settings: https://flask.palletsprojects.com/en/latest/config/#builtin-configuration-values
4 | TESTING: Optional[bool] = True
5 | SECRET_KEY: str = "NOT_VERY_SECRET"
6 |
--------------------------------------------------------------------------------
/event_api/config/test.py:
--------------------------------------------------------------------------------
1 | from peewee import SqliteDatabase
2 |
3 | DATABASE = {
4 | "name": "file:cachedb?mode=memory&cache=shared",
5 | "engine": SqliteDatabase,
6 | "pragmas": {},
7 | }
8 | """Configures an in-memory database with a shared cache for testing."""
9 |
10 | API_PREFIX: str = "events"
11 |
12 | TESTING: bool = True
13 | """Enable flask TESTING mode. This is needed to get around the default-key security check."""
14 |
--------------------------------------------------------------------------------
/event_api/endpoints/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/event_api/endpoints/__init__.py
--------------------------------------------------------------------------------
/event_api/endpoints/v1/__init__.py:
--------------------------------------------------------------------------------
1 | from .dataset_operation import *
2 | from .message_log import *
3 | from .metric_log import *
4 | from .run_status import *
5 | from .test_outcomes import *
6 |
--------------------------------------------------------------------------------
/event_api/endpoints/v2/__init__.py:
--------------------------------------------------------------------------------
1 | from .batch_pipeline_status import *
2 | from .dataset_operation import *
3 | from .event_view import *
4 | from .message_log import *
5 | from .metric_log import *
6 | from .test_outcomes import *
7 |
--------------------------------------------------------------------------------
/event_api/helpers/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/event_api/helpers/__init__.py
--------------------------------------------------------------------------------
/event_api/helpers/health.py:
--------------------------------------------------------------------------------
1 | from common.entities import DB
2 | from common.kafka import TOPIC_UNIDENTIFIED_EVENTS, KafkaProducer
3 | from common.kubernetes.readiness_probe import NotReadyException
4 |
5 |
6 | def readiness_probe() -> None:
7 | if DB.obj is None:
8 | raise NotReadyException("Database not initialized")
9 | with KafkaProducer({}) as producer:
10 | if not producer.is_topic_available(TOPIC_UNIDENTIFIED_EVENTS):
11 | raise NotReadyException("Kafka topic not ready or producer not connected")
12 |
--------------------------------------------------------------------------------
/event_api/routes/__init__.py:
--------------------------------------------------------------------------------
1 | from .v1_routes import *
2 | from .v2_routes import *
3 |
--------------------------------------------------------------------------------
/event_api/tests/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/event_api/tests/__init__.py
--------------------------------------------------------------------------------
/event_api/tests/integration/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/event_api/tests/integration/__init__.py
--------------------------------------------------------------------------------
/event_api/tests/integration/v1_endpoints/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/event_api/tests/integration/v1_endpoints/__init__.py
--------------------------------------------------------------------------------
/event_api/tests/integration/v2_endpoints/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/event_api/tests/integration/v2_endpoints/__init__.py
--------------------------------------------------------------------------------
/event_api/tests/unit/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/event_api/tests/unit/__init__.py
--------------------------------------------------------------------------------
/observability_api/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/observability_api/__init__.py
--------------------------------------------------------------------------------
/observability_api/config/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/observability_api/config/__init__.py
--------------------------------------------------------------------------------
/observability_api/config/cloud.py:
--------------------------------------------------------------------------------
1 | import os
2 |
3 | # Flask specific settings: https://flask.palletsprojects.com/en/latest/config/#builtin-configuration-values
4 | SECRET_KEY: str = os.environ["OBSERVABILITY_KEY_FLASK_SECRET"]
5 | SERVER_NAME: str = os.environ["OBSERVABILITY_API_HOSTNAME"]
6 |
7 | try:
8 | DEFAULT_JWT_EXPIRATION_SECONDS: float = float(os.environ["OBSERVABILITY_JWT_EXPIRATION_SECONDS"])
9 | except Exception:
10 | pass
11 |
--------------------------------------------------------------------------------
/observability_api/config/local.py:
--------------------------------------------------------------------------------
1 | from typing import Optional
2 |
3 | # Flask specific settings: https://flask.palletsprojects.com/en/latest/config/#builtin-configuration-values
4 | PROPAGATE_EXCEPTIONS: Optional[bool] = True
5 | SECRET_KEY: str = "NOT_VERY_SECRET"
6 |
7 | # Application settings
8 | OAUTHLIB_INSECURE_TRANSPORT: bool = True
9 | """Determines whether or not to allow single-sign-on flow when not using https."""
10 |
--------------------------------------------------------------------------------
/observability_api/config/minikube.py:
--------------------------------------------------------------------------------
1 | from typing import Optional
2 |
3 | # Flask specific settings: https://flask.palletsprojects.com/en/latest/config/#builtin-configuration-values
4 | TESTING: Optional[bool] = True
5 | SECRET_KEY: str = "NOT_VERY_SECRET"
6 |
7 | # Application settings
8 | OAUTHLIB_INSECURE_TRANSPORT: bool = True
9 | """Determines whether or not to allow single-sign-on flow when not using https."""
10 |
--------------------------------------------------------------------------------
/observability_api/config/test.py:
--------------------------------------------------------------------------------
1 | from typing import Optional
2 |
3 | # Flask specific settings: https://flask.palletsprojects.com/en/latest/config/#builtin-configuration-values
4 | PROPAGATE_EXCEPTIONS: Optional[bool] = True
5 | SECRET_KEY: str = "NOT_VERY_SECRET"
6 | TESTING: bool = True
7 |
8 | # Application settings
9 | OAUTHLIB_INSECURE_TRANSPORT: bool = True
10 | """Determines whether or not to allow single-sign-on flow when not using https."""
11 |
--------------------------------------------------------------------------------
/observability_api/endpoints/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/observability_api/endpoints/__init__.py
--------------------------------------------------------------------------------
/observability_api/endpoints/v1/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/observability_api/endpoints/v1/__init__.py
--------------------------------------------------------------------------------
/observability_api/helpers/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/observability_api/helpers/__init__.py
--------------------------------------------------------------------------------
/observability_api/helpers/health.py:
--------------------------------------------------------------------------------
1 | from common.entities import DB
2 |
3 |
4 | def readiness_probe() -> None:
5 | if DB.obj is None:
6 | raise ValueError("Database not initialized")
7 |
--------------------------------------------------------------------------------
/observability_api/routes/__init__.py:
--------------------------------------------------------------------------------
1 | __all__ = ["build_v1_routes"]
2 |
3 | from .v1_routes import build_v1_routes
4 |
--------------------------------------------------------------------------------
/observability_api/schemas/base_schemas.py:
--------------------------------------------------------------------------------
1 | __all__ = ["AuditEntitySchemaMixin", "BaseEntitySchema"]
2 | from marshmallow.fields import UUID, DateTime, Nested
3 | from marshmallow_peewee import ModelSchema
4 |
5 | from common.entities import BaseEntity, User
6 |
7 |
8 | class BaseEntitySchema(ModelSchema):
9 | id = UUID(dump_only=True)
10 |
11 | class Meta:
12 | model = BaseEntity
13 |
14 |
15 | class AuditUserSchema(BaseEntitySchema):
16 | class Meta:
17 | model = User
18 | fields = ("id", "name")
19 |
20 |
21 | class AuditEntitySchemaMixin:
22 | created_on = DateTime(dump_only=True)
23 | created_by = Nested(AuditUserSchema(), dump_only=True)
24 |
--------------------------------------------------------------------------------
/observability_api/schemas/company_schemas.py:
--------------------------------------------------------------------------------
1 | __all__ = ["CompanySchema", "CompanyPatchSchema"]
2 |
3 | from common.entities import Company
4 |
5 | from .base_schemas import AuditEntitySchemaMixin, BaseEntitySchema
6 |
7 |
8 | class CompanySchema(BaseEntitySchema, AuditEntitySchemaMixin):
9 | class Meta:
10 | model = Company
11 |
12 |
13 | class CompanyPatchSchema(CompanySchema):
14 | class Meta:
15 | fields = ("name",)
16 |
--------------------------------------------------------------------------------
/observability_api/schemas/organization_schemas.py:
--------------------------------------------------------------------------------
1 | __all__ = ["OrganizationSchema", "OrganizationPatchSchema"]
2 | from marshmallow.fields import Pluck
3 |
4 | from common.entities import Organization
5 |
6 | from .base_schemas import AuditEntitySchemaMixin, BaseEntitySchema
7 | from .company_schemas import CompanySchema
8 |
9 |
10 | class OrganizationSchema(BaseEntitySchema, AuditEntitySchemaMixin):
11 | company = Pluck(CompanySchema, "id", dump_only=True)
12 |
13 | class Meta:
14 | model = Organization
15 |
16 |
17 | class OrganizationPatchSchema(OrganizationSchema):
18 | class Meta:
19 | fields = ("name", "description")
20 |
--------------------------------------------------------------------------------
/observability_api/schemas/pipeline_schemas.py:
--------------------------------------------------------------------------------
1 | __all__ = ["PipelineSchema"]
2 |
3 | from common.entities.component import ComponentType
4 | from common.schemas.fields import EnumStr
5 | from observability_api.schemas import ComponentSchema
6 |
7 |
8 | class PipelineSchema(ComponentSchema):
9 | type = EnumStr(
10 | enum=ComponentType,
11 | load_default=ComponentType.BATCH_PIPELINE.value,
12 | dump_default=ComponentType.BATCH_PIPELINE.value,
13 | )
14 |
--------------------------------------------------------------------------------
/observability_api/schemas/project_schemas.py:
--------------------------------------------------------------------------------
1 | __all__ = ["ProjectSchema", "ProjectPatchSchema"]
2 |
3 | from marshmallow.fields import Pluck
4 |
5 | from common.entities import Project
6 |
7 | from .base_schemas import AuditEntitySchemaMixin, BaseEntitySchema
8 | from .organization_schemas import OrganizationSchema
9 |
10 |
11 | class ProjectSchema(BaseEntitySchema, AuditEntitySchemaMixin):
12 | organization = Pluck(OrganizationSchema, "id", dump_only=True)
13 |
14 | class Meta:
15 | model = Project
16 | exclude = ("agent_check_interval", "alert_actions")
17 |
18 |
19 | class ProjectPatchSchema(ProjectSchema):
20 | class Meta:
21 | fields = ("name", "description", "active")
22 |
--------------------------------------------------------------------------------
/observability_api/schemas/server_schemas.py:
--------------------------------------------------------------------------------
1 | __all__ = ["ServerSchema"]
2 |
3 | from common.entities.component import ComponentType
4 | from common.schemas.fields import EnumStr
5 | from observability_api.schemas import ComponentSchema
6 |
7 |
8 | class ServerSchema(ComponentSchema):
9 | type = EnumStr(
10 | enum=ComponentType,
11 | load_default=ComponentType.SERVER.value,
12 | dump_default=ComponentType.SERVER.value,
13 | )
14 |
--------------------------------------------------------------------------------
/observability_api/schemas/streaming_pipeline_schemas.py:
--------------------------------------------------------------------------------
1 | __all__ = ["StreamingPipelineSchema"]
2 |
3 | from common.entities.component import ComponentType
4 | from common.schemas.fields import EnumStr
5 | from observability_api.schemas import ComponentSchema
6 |
7 |
8 | class StreamingPipelineSchema(ComponentSchema):
9 | type = EnumStr(
10 | enum=ComponentType,
11 | load_default=ComponentType.STREAMING_PIPELINE.value,
12 | dump_default=ComponentType.STREAMING_PIPELINE.value,
13 | )
14 |
--------------------------------------------------------------------------------
/observability_api/schemas/testgen_dataset_component_schemas.py:
--------------------------------------------------------------------------------
1 | __all__ = ["TestgenDatasetComponentSchema"]
2 |
3 | from marshmallow.fields import List, Str
4 |
5 | from common.entities import TestgenDatasetComponent
6 | from observability_api.schemas.base_schemas import BaseEntitySchema
7 |
8 |
9 | class TestgenDatasetComponentSchema(BaseEntitySchema):
10 | table_list = List(Str())
11 | integration_name = Str(dump_only=True, dump_default="TESTGEN")
12 |
13 | class Meta:
14 | model = TestgenDatasetComponent
15 |
--------------------------------------------------------------------------------
/observability_api/schemas/user_schemas.py:
--------------------------------------------------------------------------------
1 | __all__ = ["UserSchema", "UserPatchSchema"]
2 |
3 | from marshmallow.fields import Pluck, Str
4 |
5 | from .base_schemas import AuditEntitySchemaMixin, BaseEntitySchema
6 | from .company_schemas import CompanySchema
7 |
8 |
9 | class UserSchema(BaseEntitySchema, AuditEntitySchemaMixin):
10 | primary_company = Pluck(CompanySchema, "id", dump_only=True)
11 | name = Str(required=True)
12 | email = Str(required=True)
13 | username = Str(required=False)
14 |
15 |
16 | class UserPatchSchema(UserSchema):
17 | class Meta:
18 | # excluded email and foreign_user_id; cannot be changed after creation!
19 | fields = ("name", "admin", "active")
20 |
--------------------------------------------------------------------------------
/observability_api/tests/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/observability_api/tests/__init__.py
--------------------------------------------------------------------------------
/observability_api/tests/functional/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/observability_api/tests/functional/__init__.py
--------------------------------------------------------------------------------
/observability_api/tests/integration/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/observability_api/tests/integration/__init__.py
--------------------------------------------------------------------------------
/observability_api/tests/integration/helpers/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/observability_api/tests/integration/helpers/__init__.py
--------------------------------------------------------------------------------
/observability_api/tests/integration/schemas/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/observability_api/tests/integration/schemas/__init__.py
--------------------------------------------------------------------------------
/observability_api/tests/integration/schemas/conftest.py:
--------------------------------------------------------------------------------
1 | from testlib.fixtures.entities import *
2 |
--------------------------------------------------------------------------------
/observability_api/tests/integration/v1_endpoints/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/observability_api/tests/integration/v1_endpoints/__init__.py
--------------------------------------------------------------------------------
/observability_api/tests/integration/v1_endpoints/test_converters.py:
--------------------------------------------------------------------------------
1 | from http import HTTPStatus
2 |
3 | import pytest
4 |
5 | from common.entities import Company, Organization, Project
6 |
7 |
8 | @pytest.mark.integration
9 | def test_32_uuid_converter(client, g_user_2_admin):
10 | # We have a converter which allows us to reference UUIDs by their dashless version
11 | company = Company.create(name="Foo")
12 | org = Organization.create(name="Foo", company=company)
13 | proj = Project.create(name="Foo", active=True, organization=org)
14 | response = client.get(f"/observability/v1/projects/{str(proj.id).replace('-', '')}")
15 | assert response.status_code == HTTPStatus.OK, response.json
16 | assert response.json["id"] == str(proj.id)
17 |
--------------------------------------------------------------------------------
/observability_api/tests/unit/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/observability_api/tests/unit/__init__.py
--------------------------------------------------------------------------------
/observability_api/tests/unit/helpers/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/observability_api/tests/unit/helpers/__init__.py
--------------------------------------------------------------------------------
/observability_api/tests/unit/schemas/test_testgen_test_outcome_integration_schemas.py:
--------------------------------------------------------------------------------
1 | from decimal import Decimal
2 |
3 | import pytest
4 |
5 | from observability_api.schemas import TestgenItemTestParametersSchema
6 |
7 |
8 | @pytest.mark.unit
9 | def test_testgen_item_parameters_dump():
10 | data = TestgenItemTestParametersSchema().dump({"name": "my-attr", "value": Decimal("10.0")})
11 | expected = {"value": "10.0", "name": "my-attr"}
12 | assert expected == data
13 |
--------------------------------------------------------------------------------
/observability_api/tests/unit/v1_endpoints/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/observability_api/tests/unit/v1_endpoints/__init__.py
--------------------------------------------------------------------------------
/observability_ui/.editorconfig:
--------------------------------------------------------------------------------
1 | # Editor configuration, see http://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | charset = utf-8
6 | indent_style = space
7 | indent_size = 2
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
11 | [*.md]
12 | max_line_length = off
13 | trim_trailing_whitespace = false
14 |
15 | [*.ts]
16 | ij_typescript_imports_wrap = off
17 | ij_typescript_enforce_trailing_comma = keep
18 | # ij_typescript_spaces_within_array_initializer_brackets = true
19 |
--------------------------------------------------------------------------------
/observability_ui/.prettierignore:
--------------------------------------------------------------------------------
1 | # Add files here to ignore them from prettier formatting
2 |
3 | /dist
4 | /coverage
5 |
6 | .angular
7 |
--------------------------------------------------------------------------------
/observability_ui/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true
3 | }
4 |
--------------------------------------------------------------------------------
/observability_ui/.yarnrc:
--------------------------------------------------------------------------------
1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2 | # yarn lockfile v1
3 |
4 |
5 | yarn-path ".yarn/releases/yarn-1.22.21.cjs"
6 |
--------------------------------------------------------------------------------
/observability_ui/apps/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/observability_ui/apps/.gitkeep
--------------------------------------------------------------------------------
/observability_ui/apps/basic-auth/module-federation.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | name: 'basic-auth',
3 | exposes: {
4 | './Authentication': 'apps/basic-auth/src/app/authentication/authentication.module.ts',
5 | },
6 | };
7 |
--------------------------------------------------------------------------------
/observability_ui/apps/basic-auth/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@observability/basic-auth",
3 | "version": "2.0.0",
4 | "description": "adds support for username/password authentication to the host app"
5 | }
6 |
--------------------------------------------------------------------------------
/observability_ui/apps/basic-auth/src/app/app.component.ts:
--------------------------------------------------------------------------------
1 | import { Component } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'auth-root',
5 | template: ''
6 |
7 | })
8 | export class AppComponent {}
--------------------------------------------------------------------------------
/observability_ui/apps/basic-auth/src/app/app.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { BrowserModule } from '@angular/platform-browser';
3 | import { RouterModule } from '@angular/router';
4 | import { AppComponent } from './app.component';
5 |
6 | @NgModule({
7 | declarations: [AppComponent],
8 | imports: [
9 | BrowserModule,
10 | RouterModule.forRoot([
11 | {
12 | path: '',
13 | loadChildren: () => import('./authentication/authentication.module').then(m => m.AuthenticationModule)
14 | }
15 | ], { initialNavigation: 'enabledBlocking' }),
16 | ],
17 | providers: [],
18 | bootstrap: [AppComponent],
19 | })
20 | export class AppModule {}
21 |
--------------------------------------------------------------------------------
/observability_ui/apps/basic-auth/src/app/app.routes.ts:
--------------------------------------------------------------------------------
1 | import { Route } from '@angular/router';
2 |
3 | export const appRoutes: Route[] = [
4 | {path: '', loadChildren: () => import('./authentication/authentication.module').then(m => m.AuthenticationModule)},
5 | ];
6 |
--------------------------------------------------------------------------------
/observability_ui/apps/basic-auth/src/app/authentication/authentication.component.ts:
--------------------------------------------------------------------------------
1 | import { Component } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'auth-entry',
5 | template: ``,
6 | styles: [`
7 | :host {
8 | width: 100%;
9 | height: 100%;
10 | }
11 | `],
12 | })
13 | export class AuthenticationComponent {}
14 |
--------------------------------------------------------------------------------
/observability_ui/apps/basic-auth/src/app/authentication/authentication.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { CommonModule } from '@angular/common';
3 | import { RouterModule } from '@angular/router';
4 |
5 | import { AuthenticationComponent } from './authentication.component';
6 | import { remoteRoutes } from './authentication.routes';
7 |
8 | @NgModule({
9 | declarations: [
10 | AuthenticationComponent
11 | ],
12 | imports: [
13 | CommonModule,
14 | RouterModule.forChild(remoteRoutes),
15 | ],
16 | providers: [],
17 | })
18 | export class AuthenticationModule {}
19 |
--------------------------------------------------------------------------------
/observability_ui/apps/basic-auth/src/app/logout/logout.component.html:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
You have logged out of Observability
9 |
10 |
16 |
17 |
--------------------------------------------------------------------------------
/observability_ui/apps/basic-auth/src/assets/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/observability_ui/apps/basic-auth/src/assets/.gitkeep
--------------------------------------------------------------------------------
/observability_ui/apps/basic-auth/src/bootstrap.ts:
--------------------------------------------------------------------------------
1 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
2 | import { AppModule } from './app/app.module';
3 |
4 | platformBrowserDynamic()
5 | .bootstrapModule(AppModule)
6 | .catch((err) => console.error(err));
7 |
--------------------------------------------------------------------------------
/observability_ui/apps/basic-auth/src/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/observability_ui/apps/basic-auth/src/favicon.ico
--------------------------------------------------------------------------------
/observability_ui/apps/basic-auth/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | basic-auth
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/observability_ui/apps/basic-auth/src/main.ts:
--------------------------------------------------------------------------------
1 | import('./bootstrap').catch(err => console.error(err));
2 |
--------------------------------------------------------------------------------
/observability_ui/apps/basic-auth/src/styles.scss:
--------------------------------------------------------------------------------
1 | /* You can add global styles to this file, and also import other style files */
2 |
--------------------------------------------------------------------------------
/observability_ui/apps/basic-auth/src/test-setup.ts:
--------------------------------------------------------------------------------
1 | import 'jest-preset-angular/setup-jest';
2 |
--------------------------------------------------------------------------------
/observability_ui/apps/basic-auth/tsconfig.app.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../../dist/out-tsc",
5 | "types": [],
6 | "target": "ES2022"
7 | },
8 | "files": [
9 | "src/main.ts"
10 | ],
11 | "include": [
12 | "src/**/*.d.ts"
13 | ],
14 | "exclude": [
15 | "jest.config.ts",
16 | "src/**/*.test.ts",
17 | "src/**/*.spec.ts"
18 | ]
19 | }
20 |
--------------------------------------------------------------------------------
/observability_ui/apps/basic-auth/tsconfig.editor.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "include": [
4 | "src/**/*.ts"
5 | ],
6 | "compilerOptions": {
7 | "types": [
8 | "jest",
9 | "node"
10 | ]
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/observability_ui/apps/basic-auth/tsconfig.spec.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../../dist/out-tsc",
5 | "module": "commonjs",
6 | "target": "es2016",
7 | "types": ["jest", "node"],
8 | "noImplicitAny": false,
9 | },
10 | "files": ["src/test-setup.ts"],
11 | "include": [
12 | "jest.config.ts",
13 | "src/**/*.test.ts",
14 | "src/**/*.spec.ts",
15 | "src/**/*.d.ts"
16 | ]
17 | }
18 |
--------------------------------------------------------------------------------
/observability_ui/apps/basic-auth/webpack.config.js:
--------------------------------------------------------------------------------
1 | const { CreateConfig } = require('../../libs/webpack-config');
2 | const moduleFedarationConfig = require('./module-federation.config');
3 |
4 | module.exports = CreateConfig(moduleFedarationConfig);
5 |
--------------------------------------------------------------------------------
/observability_ui/apps/basic-auth/webpack.prod.config.js:
--------------------------------------------------------------------------------
1 | module.exports = require('./webpack.config');
2 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/module-federation.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | name: 'shell',
3 | remotes: []
4 | };
5 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@observability/shell",
3 | "version": "2.0.0",
4 | "description": "this is the shell app of observability mfe setup",
5 | "license": "MIT"
6 | }
7 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/app/app-version/app-version.component.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/observability_ui/apps/shell/src/app/app-version/app-version.component.css
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/app/app-version/app-version.component.html:
--------------------------------------------------------------------------------
1 | There is a new version available.
2 | {{newVersion$ | async | json}}
3 |
4 | or
5 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/app/app-version/app-version.component.ts:
--------------------------------------------------------------------------------
1 | import { Component } from '@angular/core';
2 | import { AppVersionService } from './app-version.service';
3 |
4 | @Component({
5 | selector: 'shell-app-version',
6 | templateUrl: './app-version.component.html',
7 | styleUrls: [ './app-version.component.css' ]
8 | })
9 | export class AppVersionComponent {
10 |
11 | newVersion$ = this.appVersion.nextVersion$;
12 |
13 | constructor(
14 | private appVersion: AppVersionService,
15 | ) {}
16 |
17 | reloadPage() {
18 | window.location.reload();
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/app/app.component.scss:
--------------------------------------------------------------------------------
1 | @use '@angular/material' as mat;
2 |
3 | .container {
4 | display: flex;
5 | flex-direction: column;
6 | position: absolute;
7 | top: 0;
8 | bottom: 0;
9 | left: 0;
10 | right: 0;
11 | }
12 |
13 | .sidenav-container {
14 | flex: 1;
15 |
16 | &--menu {
17 | @include mat.elevation(8);
18 |
19 | width: 200px;
20 | }
21 | }
22 |
23 | .main-content {
24 | display: flex;
25 | flex-direction: column;
26 | height: 100%;
27 | overflow: hidden;
28 | }
29 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/app/components/default-error-handler/default-error.handler.ts:
--------------------------------------------------------------------------------
1 | import { ErrorHandler, Injectable } from '@angular/core';
2 | import { MatLegacySnackBar as MatSnackBar } from '@angular/material/legacy-snack-bar';
3 | import { DefaultErrorHandlerComponent } from './default-error-handler.component';
4 |
5 |
6 | @Injectable({
7 | providedIn: 'root'
8 | })
9 | export class DefaultErrorHandler extends ErrorHandler {
10 |
11 | constructor(
12 | private snackbar: MatSnackBar,
13 | ) {
14 | super();
15 | }
16 |
17 | override handleError(error: any) {
18 | super.handleError(error);
19 | this.snackbar.openFromComponent(DefaultErrorHandlerComponent, {duration: 3000, data: error, });
20 | }
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/app/components/email-action/email-action.component.scss:
--------------------------------------------------------------------------------
1 | @use '@observability/ui/styles/mixins' as mixins;
2 | @use '@observability/ui/styles/variables' as variables;
3 |
4 | :host {
5 | display: flex;
6 | flex-direction: column;
7 | width: 100%;
8 | }
9 |
10 | .not-configured {
11 | padding: 8px 0;
12 | }
13 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/app/components/offline/offline.component.html:
--------------------------------------------------------------------------------
1 | offline works!
2 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/app/components/offline/offline.component.scss:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/observability_ui/apps/shell/src/app/components/offline/offline.component.scss
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/app/components/offline/offline.component.ts:
--------------------------------------------------------------------------------
1 | import { Component } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'shell-offline',
5 | templateUrl: './offline.component.html',
6 | styleUrls: [ './offline.component.scss' ]
7 | })
8 | export class OfflineComponent {
9 | }
10 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/app/components/rules-actions/action/action-template.component.scss:
--------------------------------------------------------------------------------
1 | @use '@observability/ui/styles/variables' as vars;
2 |
3 | mat-panel-title {
4 | min-width: 80px;
5 | }
6 |
7 | mat-expansion-panel {
8 | border: vars.$border;
9 | }
10 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/app/components/rules-actions/alert/templating-alert.component.scss:
--------------------------------------------------------------------------------
1 | @use '@observability/ui/styles/mixins' as mixins;
2 | @use '@observability/ui/styles/variables' as variables;
3 |
4 | :host {
5 | @include mixins.flex-row();
6 |
7 | * {
8 | font-size: 14px;
9 | color: variables.$dark-accent-text;
10 | font-weight: normal;
11 | }
12 |
13 | mat-icon {
14 | @include mixins.icon-size(16px)
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/app/components/rules-actions/implementations/rules/example/example-rule-label.component.ts:
--------------------------------------------------------------------------------
1 | import { Component } from '@angular/core';
2 |
3 | @Component({
4 | // eslint-disable-next-line @angular-eslint/component-selector
5 | selector: 'label-example-rule',
6 | template: `🌈 example rule label 🦄`,
7 | standalone: true,
8 | styles: [ `
9 | .label {
10 | text-transform: capitalize;
11 | }
12 | ` ],
13 | })
14 | export class ExampleRuleLabelComponent {
15 | }
16 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/app/components/rules-actions/implementations/rules/run-state/run-state-rule.component.scss:
--------------------------------------------------------------------------------
1 | @use '@observability/ui/styles/mixins' as mixins;
2 |
3 | :host {
4 | display: flex;
5 | flex-direction: row;
6 | }
7 |
8 | .count-input {
9 | width: 32px;
10 | }
11 |
12 | .advanced-options-link-container {
13 | display: flex;
14 | width: 100%;
15 | margin-top: 16px;
16 | font-size: 12px;
17 |
18 | .advanced-options-link {
19 | @include mixins.link();
20 | @include mixins.link-with-icon();
21 | @include mixins.flex-row();
22 |
23 | mat-icon {
24 | @include mixins.icon-size(14px);
25 | margin-left: 2px;
26 | }
27 | }
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/app/components/rules-actions/rule.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@angular/core';
2 | import { EntityService, EntityType } from '@observability-ui/core';
3 | import { Rule } from './rule.model';
4 |
5 |
6 | @Injectable({
7 | providedIn: 'root'
8 | })
9 | export class RuleService extends EntityService {
10 | protected override baseEntity: EntityType = EntityType.Rule;
11 | protected override parentEntity = EntityType.Journey;
12 | }
13 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/app/components/sidenav-menu/sidenav-menu.model.ts:
--------------------------------------------------------------------------------
1 | import { ComponentType } from '@angular/cdk/overlay';
2 |
3 | export interface Menu {
4 | label: string;
5 | items: (MenuItemLink|MenuItemComponent)[];
6 | }
7 |
8 | export interface MenuItemLink {
9 | icon: string;
10 | label: string;
11 | link: any[];
12 | }
13 |
14 | export interface MenuItemComponent {
15 | component: ComponentType
16 | }
17 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/app/components/summary-item/summary-item.component.html:
--------------------------------------------------------------------------------
1 |
3 |
{{label}}
4 |
{{count}}
5 |
6 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/app/components/summary-item/summary-item.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, Input } from '@angular/core';
2 | import { NgClass, NgStyle } from '@angular/common';
3 |
4 | @Component({
5 | selector: 'shell-summary-item',
6 | templateUrl: 'summary-item.component.html',
7 | styleUrls: [ 'summary-item.component.scss' ],
8 | imports: [
9 | NgStyle,
10 | NgClass
11 | ],
12 | standalone: true
13 | })
14 |
15 | export class SummaryItemComponent {
16 | @Input() count: number;
17 | @Input() color: string;
18 | @Input() label: string;
19 | }
20 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/app/components/summary/summary.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/app/components/summary/summary.component.scss:
--------------------------------------------------------------------------------
1 | @use '@observability/ui/styles/mixins' as mixins;
2 |
3 | :host {
4 | width: 100%;
5 | }
6 |
7 | .items-container {
8 | @include mixins.flex-row($justify: flex-start);
9 | }
10 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/app/components/summary/summary.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { ComponentFixture, TestBed } from '@angular/core/testing';
2 | import { SummaryComponent } from './summary.component';
3 |
4 | describe('summary', () => {
5 | let component: SummaryComponent;
6 | let fixture: ComponentFixture;
7 |
8 | beforeEach(async () => {
9 | await TestBed.configureTestingModule({
10 | imports: [ SummaryComponent, ],
11 | }).compileComponents();
12 |
13 | fixture = TestBed.createComponent(SummaryComponent);
14 | component = fixture.componentInstance;
15 |
16 | fixture.detectChanges();
17 | });
18 |
19 | it('should create', () => {
20 | expect(component).toBeTruthy();
21 | });
22 | });
23 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/app/guards/is-online.guard.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@angular/core';
2 | import { Router, UrlTree } from '@angular/router';
3 |
4 | @Injectable({
5 | providedIn: 'root'
6 | })
7 | export class IsOnlineGuard {
8 | constructor(private router: Router) {}
9 |
10 | canActivate(): boolean | UrlTree {
11 | return navigator.onLine || this.router.parseUrl('/offline');
12 | }
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/app/projects/api-keys/api-keys.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@angular/core';
2 | import { EntityService, EntityType, ServiceKey } from '@observability-ui/core';
3 |
4 | @Injectable({
5 | providedIn: 'root'
6 | })
7 | export class APIKeysService extends EntityService {
8 |
9 | protected override parentEntity = EntityType.Project;
10 | protected override baseEntity = EntityType.ServiceKey;
11 | }
12 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/app/projects/api-keys/api-keys.store.spec.ts:
--------------------------------------------------------------------------------
1 | import { TestBed } from '@angular/core/testing';
2 | import { APIKeysStore } from './api-keys.store';
3 | import { MockProvider } from '@datakitchen/ngx-toolkit';
4 | import { APIKeysService } from './api-keys.service';
5 |
6 | describe('api-keys.store', () => {
7 |
8 | let store: APIKeysStore;
9 |
10 | beforeEach(async () => {
11 | await TestBed.configureTestingModule({
12 |
13 | providers: [
14 | APIKeysStore,
15 | MockProvider(APIKeysService)
16 | ],
17 | });
18 |
19 | store = TestBed.inject(APIKeysStore);
20 |
21 | });
22 |
23 | it('should create', () => {
24 | expect(store).toBeTruthy();
25 | });
26 |
27 | });
28 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/app/projects/components/add-component-dialog/add-component-dialog.component.scss:
--------------------------------------------------------------------------------
1 | @use '@observability/ui/styles/variables' as variables;
2 | @use '@observability/ui/styles/mixins' as mixins;
3 |
4 | mat-form-field {
5 | width: 100%;
6 | }
7 |
8 | textarea {
9 | resize: none;
10 | width: 100%;
11 | }
12 |
13 | .top-margin {
14 | margin-top: 8px
15 | }
16 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/app/projects/components/add-component-dialog/add-component-dialog.translation.ts:
--------------------------------------------------------------------------------
1 | export const addComponentDialogTranslation = {
2 | addComponentDialog: {
3 | title: 'Add Component',
4 | required: 'Field is required',
5 | existing: 'Key already in use',
6 | componentType: 'Component Type',
7 | cancel: 'Cancel',
8 | adding: 'Adding',
9 | add: 'Add'
10 | }
11 | };
12 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/app/projects/components/components-list/component-list.translation.ts:
--------------------------------------------------------------------------------
1 | export const componentListTranslation = {
2 | key: 'Key',
3 | addComponent: 'Add Component',
4 | noComponents: 'No components found.',
5 | componentTypes: 'Component Types',
6 | allComponentTypes: 'All Component Types',
7 | emptyComponentsList: {
8 | title: 'No components? Begin by connecting your Data Estate',
9 | description: 'Integrate your tools so the system can create components when it receives events',
10 | button: 'Go to Integrations',
11 | learnMore: 'Get started with Observability'
12 | }
13 | };
14 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/app/projects/components/components-routing.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { RouterModule } from '@angular/router';
3 | import { ComponentsListComponent } from './components-list/components-list.component';
4 |
5 | @NgModule({
6 | imports: [
7 | RouterModule.forChild([
8 | {
9 | path: '',
10 | component: ComponentsListComponent,
11 | data: {
12 | helpLink: 'article/dataops-observability-help/components'
13 | },
14 | },
15 | ]),
16 |
17 | ],
18 | exports: [ RouterModule ],
19 | })
20 | export class ComponentsRoutingModule {
21 | }
22 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/app/projects/events/batch-runs/batch-runs.component.scss:
--------------------------------------------------------------------------------
1 | :host {
2 | display: flex;
3 | flex-direction: column;
4 | flex-grow: 1;
5 | }
6 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/app/projects/events/event-list/event-list.component.scss:
--------------------------------------------------------------------------------
1 | :host {
2 | display: flex;
3 | flex-direction: column;
4 | flex-grow: 1;
5 | }
6 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/app/projects/events/events.component.html:
--------------------------------------------------------------------------------
1 |
2 |
{{'events' | translate | titlecase}}
3 |
4 |
5 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/app/projects/events/events.component.scss:
--------------------------------------------------------------------------------
1 | :host {
2 | display: flex;
3 | flex-direction: column;
4 | height: 100%;
5 | width: 100%;
6 | }
7 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/app/projects/events/events.component.ts:
--------------------------------------------------------------------------------
1 | import { Component } from '@angular/core';
2 | import { CoreComponent } from '@datakitchen/ngx-toolkit';
3 |
4 | @Component({
5 | selector: 'shell-events',
6 | templateUrl: 'events.component.html',
7 | styleUrls: [ 'events.component.scss' ],
8 | })
9 | export class EventsComponent extends CoreComponent {
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/app/projects/instances/instance-events/instance-events.component.scss:
--------------------------------------------------------------------------------
1 | @use '@observability/ui/styles/mixins' as mixins;
2 | @use '@observability/ui/styles/variables' as variables;
3 |
4 | :host {
5 | @include mixins.flex-column($justify: flex-start, $align: stretch);
6 |
7 | flex: 1;
8 | }
9 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/app/projects/instances/instance-runs/instance-runs.component.scss:
--------------------------------------------------------------------------------
1 | @use '@observability/ui/styles/mixins' as mixins;
2 | @use '@observability/ui/styles/variables' as variables;
3 |
4 | :host {
5 | @include mixins.flex-column($justify: flex-start, $align: stretch);
6 | flex: 1;
7 | }
8 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/app/projects/integrations/integrations.model.ts:
--------------------------------------------------------------------------------
1 | import { InjectionToken } from '@angular/core';
2 | import { AbstractTool } from './tools/abstract-tool.directive';
3 |
4 | export type ToolIcon = {_name: string; _displayName: string; _icon: string};
5 |
6 | export const INTEGRATION_TOOLS = new InjectionToken('INTEGRATION_TOOLS', {
7 | providedIn: 'root',
8 | factory: () => []
9 | });
10 |
11 | export const EXTRA_TOOL_ICONS = new InjectionToken('EXTRA_TOOL_ICONS', {
12 | providedIn: 'root',
13 | factory: () => []
14 | });
15 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/app/projects/integrations/integrations.translations.ts:
--------------------------------------------------------------------------------
1 | export const integrationsTranslations = {
2 | noIntegrations: 'No integrations found.',
3 | integrations: 'Integrations',
4 | setup: {
5 | title: 'Connect to your Data Estate',
6 | subtitle: 'Configure agents to integrate your tools and send events to DataOps Observability',
7 | learnMoreAbout: 'Learn more about'
8 | },
9 | availableIntegrations: 'View Available Agents',
10 | searchIntegrations: 'Search Integrations',
11 | alert: 'Don’t see the integration you need? Build your own using our',
12 | alertLink: 'agent framework'
13 | };
14 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/app/projects/journeys/journey-details/journey-details.component.scss:
--------------------------------------------------------------------------------
1 | :host {
2 | height: 100%;
3 | display: flex;
4 | flex-direction: column;
5 | }
6 |
7 | nav {
8 | .link {
9 | opacity: 1 !important;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/app/projects/journeys/journey-rules/journey-rules.component.scss:
--------------------------------------------------------------------------------
1 | @use '@observability/ui/styles/variables' as vars;
2 | @use '@observability/ui/styles/mixins' as mixins;
3 |
4 | mat-progress-spinner {
5 | margin: auto;
6 | }
7 |
8 | .rule {
9 | padding: vars.$space-xs vars.$space-xs;
10 | border: vars.$border;
11 | background: vars.$white;
12 | border: vars.$border;
13 | margin-top: vars.$space-xs;
14 |
15 | &:last-child {
16 | margin-bottom: vars.$space-md;
17 | }
18 | }
19 |
20 | .action {
21 | padding: vars.$space-xs;
22 | }
23 |
24 | :host ::ng-deep .add-rule-button span {
25 | @include mixins.flex-row();
26 |
27 | mat-icon {
28 | margin-right: 4px;
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/app/projects/journeys/no-components-dialog/no-components-dialog.component.scss:
--------------------------------------------------------------------------------
1 | @use '@observability/ui/styles/variables' as variables;
2 |
3 | .no-components-setup {
4 | border: none;
5 | padding: 0;
6 | height: auto;
7 |
8 | .title {
9 | font-size: 18px;
10 | margin-top: variables.$space-sm;
11 | }
12 | }
13 |
14 | .body {
15 | text-align: center;
16 | margin-top: variables.$space-sm;
17 | }
18 |
19 | .add-button {
20 | margin-top: variables.$space-lg;
21 | margin-bottom: variables.$space-lg;
22 | }
23 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/app/projects/project-display/project-display.component.scss:
--------------------------------------------------------------------------------
1 | @use '@observability/ui/styles/mixins' as mixins;
2 | @use '@observability/ui/styles/variables' as variables;
3 |
4 | .project-container {
5 | margin-left: variables.$space-md;
6 | margin-bottom: variables.$space-sm;
7 | margin-top: variables.$space-xs;
8 |
9 | .project-label {
10 | @include mixins.font-style($style: caption, $color: secondary);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/app/projects/runs-table/runs-table.module.ts:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/observability_ui/apps/shell/src/app/projects/runs-table/runs-table.module.ts
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/app/projects/runs/run-events/run-events.component.scss:
--------------------------------------------------------------------------------
1 | @use '@observability/ui/styles/mixins' as mixins;
2 | @use '@observability/ui/styles/variables' as variables;
3 |
4 | :host {
5 | @include mixins.flex-column($justify: flex-start, $align: stretch);
6 |
7 | flex: 1;
8 | }
9 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/app/projects/runs/run-timeline/run-timeline.component.scss:
--------------------------------------------------------------------------------
1 | @use '@observability/ui/styles/mixins' as mixins;
2 | @use '@observability/ui/styles/variables' as variables;
3 |
4 | :host {
5 | display: flex;
6 | flex-direction: column;
7 | height: 100%;
8 | width: 100%;
9 | }
10 |
11 | mat-card {
12 | height: 100%;
13 | }
14 |
15 | gantt-chart {
16 | max-height: 100%;
17 | }
18 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/app/projects/runs/runs-table/run-states/run-states.component.html:
--------------------------------------------------------------------------------
1 |
2 | {{'runStatus.' + state | translate}}
3 | warning_amber
4 |
5 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/app/projects/runs/runs-table/run-time/run-time.component.scss:
--------------------------------------------------------------------------------
1 | @use '@observability/ui/styles/mixins' as mixins;
2 | @use '@observability/ui/styles/variables' as variables;
3 |
4 | small {
5 | font-size: 10px;
6 | @include mixins.font-color(disabled);
7 | }
8 |
9 | mat-icon {
10 | @include mixins.icon-size(16px);
11 |
12 | color: variables.$red-500;
13 | }
14 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/app/projects/runs/runs.translation.ts:
--------------------------------------------------------------------------------
1 | import { MessageLogLevel } from '@observability-ui/core';
2 |
3 | export const runsTranslation = {
4 | allTasks: 'All Tasks',
5 | noSelectedTask: 'Tasks',
6 |
7 | backToRuns: 'Back to Batch Runs',
8 | component_id: 'Component ID',
9 |
10 | graph: {
11 | errors: {
12 | renderingError: 'Unable to render the graph',
13 | action: 'Refresh',
14 | },
15 | },
16 | events: {
17 | logLevels: {
18 | [MessageLogLevel.Error]: 'Error',
19 | [MessageLogLevel.Warning]: 'Warning',
20 | [MessageLogLevel.Info]: 'Info',
21 | },
22 | },
23 | taskKey: 'Task Key',
24 | observedGraph: 'Observed Graph'
25 | };
26 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/app/projects/settings/settings.component.scss:
--------------------------------------------------------------------------------
1 | @use '@observability/ui/styles/mixins' as mixins;
2 | @use '@observability/ui/styles/variables' as variables;
3 |
4 | :host {
5 | display: flex;
6 | flex-direction: column;
7 | height: 100%;
8 | width: 100%;
9 | }
10 |
11 | mat-form-field {
12 | width: 100%;
13 | }
14 |
15 | .scrolling-content {
16 | max-width: 700px;
17 | }
18 |
19 | .bottom-chip {
20 | font-size: 12px;
21 | color: variables.$gray-700;
22 | border: 2px solid variables.$gray-200;
23 | padding: variables.$space-xxs variables.$space-xs;
24 | border-radius: 2px;
25 | background: variables.$gray-100;
26 | }
27 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/app/projects/task-test-summary/task-test-summary.utils.ts:
--------------------------------------------------------------------------------
1 | type AggregatedSummary = {
2 | [status in T['status']]?: number;
3 | } & { TOTAL: number };
4 |
5 | export function getCompleteSummary(summaries: T[] = []): AggregatedSummary {
9 | const aggregate: AggregatedSummary = { TOTAL: 0 };
10 | for (const item of summaries) {
11 | aggregate[item.status as T['status']] = (aggregate[item.status as T['status']] ?? 0) + (item.count ?? 1) as any;
12 | aggregate.TOTAL += item.count;
13 | }
14 |
15 | return aggregate;
16 | }
17 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/app/services/project-runs/project-runs.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@angular/core';
2 | import { EntityService, EntityType, Run } from '@observability-ui/core';
3 |
4 | @Injectable({
5 | providedIn: 'root'
6 | })
7 | export class ProjectRunsService extends EntityService {
8 | protected override parentEntity = EntityType.Project;
9 | protected override baseEntity = EntityType.Run;
10 | }
11 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/app/services/run-events/run-events.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@angular/core';
2 | import { EntityService, EntityType, EventType } from '@observability-ui/core';
3 |
4 | @Injectable({
5 | providedIn: 'root'
6 | })
7 | export class RunEventsService extends EntityService {
8 |
9 | protected override parentEntity = EntityType.Run;
10 | protected override baseEntity = EntityType.Event;
11 | }
12 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/app/stores/run-events/run-events.store.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@angular/core';
2 | import { EntityActions, EntityState, EntityStore, EventType } from '@observability-ui/core';
3 | import { RunEventsService } from '../../services/run-events/run-events.service';
4 | import { makeStore } from '@microphi/store';
5 |
6 | @Injectable({
7 | providedIn: 'root'
8 | })
9 | export class RunEventsStore extends EntityStore, EntityActions> implements makeStore, EntityActions> {
10 | constructor(protected service: RunEventsService) {
11 | super({
12 | list: [],
13 | total: 0,
14 | });
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/app/stores/run-tasks/run-tasks.store.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@angular/core';
2 | import { EntityActions, EntityState, EntityStore, RunTask } from '@observability-ui/core';
3 | import { RunTasksService } from '../../services/run-tasks/run-tasks.service';
4 | import { makeStore } from '@microphi/store';
5 |
6 | @Injectable({
7 | providedIn: 'root'
8 | })
9 | /**
10 | * TODO this should be under the RunStore
11 | */
12 | export class RunTasksStore extends EntityStore, EntityActions> implements makeStore, EntityActions> {
13 |
14 | constructor(protected service: RunTasksService) {
15 | super({
16 | total: 0,
17 | list: []
18 | });
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/assets/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/observability_ui/apps/shell/src/assets/.gitkeep
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/assets/databricks.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/assets/dataset.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/assets/icons/icon-128x128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/observability_ui/apps/shell/src/assets/icons/icon-128x128.png
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/assets/icons/icon-144x144.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/observability_ui/apps/shell/src/assets/icons/icon-144x144.png
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/assets/icons/icon-152x152.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/observability_ui/apps/shell/src/assets/icons/icon-152x152.png
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/assets/icons/icon-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/observability_ui/apps/shell/src/assets/icons/icon-192x192.png
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/assets/icons/icon-384x384.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/observability_ui/apps/shell/src/assets/icons/icon-384x384.png
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/assets/icons/icon-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/observability_ui/apps/shell/src/assets/icons/icon-512x512.png
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/assets/icons/icon-72x72.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/observability_ui/apps/shell/src/assets/icons/icon-72x72.png
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/assets/icons/icon-96x96.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/observability_ui/apps/shell/src/assets/icons/icon-96x96.png
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/assets/module-federation.manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "basic-auth": {
3 | "routePath": "authentication",
4 | "remoteEntry": "http://localhost:4201/remoteEntry.js",
5 | "remoteName": "basic-auth",
6 | "exposedModule": "./Authentication",
7 | "exposedModuleName": "AuthenticationModule"
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/assets/server.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/declarations.d.ts:
--------------------------------------------------------------------------------
1 | declare module "*.tpl" {
2 | const value: string;
3 | export default value;
4 | }
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/environments/environment.json:
--------------------------------------------------------------------------------
1 | {
2 | "apiBaseUrl": "/api"
3 | }
4 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/environments/environment.prod.ts:
--------------------------------------------------------------------------------
1 | export const environment = {
2 | production: true,
3 | };
4 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/observability_ui/apps/shell/src/favicon.ico
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/main.ts:
--------------------------------------------------------------------------------
1 | import('./bootstrap').catch((err) => console.error(err));
2 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/module-federation.manifest.prod.json:
--------------------------------------------------------------------------------
1 | {
2 | "basic-auth": {
3 | "routePath": "authentication",
4 | "remoteEntry": "/auth/remoteEntry.js",
5 | "remoteName": "basic-auth",
6 | "exposedModule": "./Authentication",
7 | "exposedModuleName": "AuthenticationModule"
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/src/test-setup.ts:
--------------------------------------------------------------------------------
1 | import 'jest-preset-angular/setup-jest';
2 |
3 | class ResizeObserver {
4 | // eslint-disable-next-line @typescript-eslint/no-empty-function
5 | observe() {}
6 | // eslint-disable-next-line @typescript-eslint/no-empty-function
7 | unobserve() {}
8 | // eslint-disable-next-line @typescript-eslint/no-empty-function
9 | disconnect() {}
10 | }
11 |
12 | window.ResizeObserver = ResizeObserver;
13 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/tsconfig.app.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../../dist/out-tsc",
5 | "types": [],
6 | "target": "ES2022",
7 | "useDefineForClassFields": false
8 | },
9 | "files": ["src/main.ts", "src/polyfills.ts"],
10 | "include": ["src/**/*.d.ts"],
11 | "exclude": ["**/*.test.ts", "**/*.spec.ts", "jest.config.ts"]
12 | }
13 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/tsconfig.editor.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "include": ["**/*.ts"],
4 | "compilerOptions": {
5 | "types": ["jest", "node"]
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/tsconfig.spec.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../../dist/out-tsc",
5 | "module": "commonjs",
6 | "types": ["jest", "node"],
7 | "target": "es2016",
8 | "noImplicitAny": false,
9 | },
10 | "files": ["src/test-setup.ts"],
11 | "include": ["**/*.test.ts", "**/*.spec.ts", "**/*.d.ts", "jest.config.ts"]
12 | }
13 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/webpack.config.js:
--------------------------------------------------------------------------------
1 | const { CreateConfig } = require("../../libs/webpack-config");
2 | const moduleFedarationConfig = require('./module-federation.config');
3 |
4 | module.exports = CreateConfig(moduleFedarationConfig);
5 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/webpack.dev.config.js:
--------------------------------------------------------------------------------
1 | module.exports = require('./webpack.config');
2 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/webpack.prod.config.js:
--------------------------------------------------------------------------------
1 | module.exports = require('./webpack.dev.config');
2 |
--------------------------------------------------------------------------------
/observability_ui/apps/shell/webpack.staging.config.js:
--------------------------------------------------------------------------------
1 | module.exports = require('./webpack.dev.config');
2 |
--------------------------------------------------------------------------------
/observability_ui/jest.preset.js:
--------------------------------------------------------------------------------
1 | const nxPreset = require('@nx/jest/preset').default;
2 |
3 | module.exports = {
4 | ...nxPreset,
5 | };
6 |
--------------------------------------------------------------------------------
/observability_ui/lerna.json:
--------------------------------------------------------------------------------
1 | {
2 | "packages": [
3 | "apps/*",
4 | "libs/*"
5 | ],
6 | "npmClient": "yarn",
7 | "version": "2.0.0",
8 | "granularPathspec": false,
9 | "command": {}
10 | }
11 |
--------------------------------------------------------------------------------
/observability_ui/libs/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/observability_ui/libs/.gitkeep
--------------------------------------------------------------------------------
/observability_ui/libs/core/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@observability/core",
3 | "version": "2.0.0",
4 | "description": "this is the core lib of observability mfe setup",
5 | "license": "MIT"
6 | }
7 |
--------------------------------------------------------------------------------
/observability_ui/libs/core/src/lib/actions/actions.model.ts:
--------------------------------------------------------------------------------
1 | import { InjectionToken } from '@angular/core';
2 | import { RunProcessedStatus } from '../models';
3 | import { AbstractAction } from './abstract-action/abstract-action.directive';
4 |
5 | export const TaskStatusEmailTemplate = {
6 | [RunProcessedStatus.Running]: 'task_status_started',
7 | [RunProcessedStatus.Completed]: 'task_status_completed',
8 | [RunProcessedStatus.CompletedWithWarnings]: 'task_status_warning',
9 | [RunProcessedStatus.Failed]: 'task_status_error',
10 | };
11 |
12 | export const RULE_ACTIONS = new InjectionToken('RULE_ACTIONS');
13 |
--------------------------------------------------------------------------------
/observability_ui/libs/core/src/lib/actions/index.ts:
--------------------------------------------------------------------------------
1 | export * from './actions.model';
2 | export * from './abstract-action/abstract-action.directive';
3 |
--------------------------------------------------------------------------------
/observability_ui/libs/core/src/lib/config/app-configuration.ts:
--------------------------------------------------------------------------------
1 | export interface AppConfiguration {
2 | apiBaseUrl: string;
3 | }
4 |
--------------------------------------------------------------------------------
/observability_ui/libs/core/src/lib/config/index.ts:
--------------------------------------------------------------------------------
1 | export * from './app-configuration';
2 | export * from './config.service';
3 | export * from './provide-from-config';
4 |
5 |
--------------------------------------------------------------------------------
/observability_ui/libs/core/src/lib/config/provide-from-config.ts:
--------------------------------------------------------------------------------
1 | /* istanbul ignore file */
2 | import { ConfigService } from './config.service';
3 | import { filter, map, take } from 'rxjs';
4 | import { AppConfiguration } from './app-configuration';
5 |
6 | export function ProvideFromConfig(provide: any, key: keyof AppConfiguration, mapFn: (value: any) => any = (v) => v) {
7 | return {
8 | provide: provide,
9 | useFactory: (config: ConfigService) => {
10 | return config.ready$.pipe(
11 | filter((ready) => ready),
12 | map(() => {
13 | return config.get(key);
14 | }),
15 | map((value) => mapFn(value)),
16 | take(1),
17 | );
18 |
19 | },
20 | deps: [ ConfigService ]
21 | };
22 | }
23 |
--------------------------------------------------------------------------------
/observability_ui/libs/core/src/lib/decorators/index.ts:
--------------------------------------------------------------------------------
1 | export * from './host-resize/host-resize';
2 |
--------------------------------------------------------------------------------
/observability_ui/libs/core/src/lib/entities/agent/agent.model.ts:
--------------------------------------------------------------------------------
1 | import { Entity } from '../../entity';
2 |
3 | export interface Agent extends Entity {
4 | key: string;
5 | tool: string;
6 | version: string;
7 | status: AgentStatus;
8 | latest_heartbeat: string;
9 | latest_event_timestamp?: string;
10 | }
11 |
12 | export enum AgentStatus {
13 | Online = 'ONLINE',
14 | Unhealthy = 'UNHEALTHY',
15 | Offline = 'OFFLINE',
16 | }
17 |
--------------------------------------------------------------------------------
/observability_ui/libs/core/src/lib/entities/agent/service/agent.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@angular/core';
2 | import { EntityService, EntityType } from '../../../entity';
3 | import { Agent } from '../agent.model';
4 |
5 |
6 | @Injectable({
7 | providedIn: 'root'
8 | })
9 | export class AgentService extends EntityService{
10 | protected readonly baseEntity = EntityType.Agent;
11 | protected override readonly parentEntity = EntityType.Project;
12 | }
13 |
--------------------------------------------------------------------------------
/observability_ui/libs/core/src/lib/entities/agent/store/agent.actions.ts:
--------------------------------------------------------------------------------
1 | import { EntityActions } from '../../../entity';
2 | import { Agent } from '../agent.model';
3 |
4 | export interface AgentActions extends EntityActions {
5 | }
6 |
--------------------------------------------------------------------------------
/observability_ui/libs/core/src/lib/entities/agent/store/agent.state.ts:
--------------------------------------------------------------------------------
1 | import { EntityState } from '../../../entity';
2 | import { Agent } from '../agent.model';
3 |
4 | export interface AgentState extends EntityState {
5 | }
6 |
--------------------------------------------------------------------------------
/observability_ui/libs/core/src/lib/entities/agent/store/agent.store.spec.ts:
--------------------------------------------------------------------------------
1 | import { TestBed } from '@angular/core/testing';
2 | import { AgentService, AgentStore } from '../../';
3 | import { MockProvider } from '@datakitchen/ngx-toolkit';
4 |
5 | describe('agent.store', () => {
6 |
7 | let store: AgentStore;
8 |
9 | beforeEach(() => {
10 | TestBed.configureTestingModule({
11 | providers: [
12 | AgentStore,
13 | MockProvider(AgentService)
14 | ],
15 | });
16 |
17 | store = TestBed.inject(AgentStore);
18 |
19 | });
20 |
21 | it('should create', () => {
22 | expect(store).toBeTruthy();
23 | });
24 |
25 | });
26 |
--------------------------------------------------------------------------------
/observability_ui/libs/core/src/lib/entities/agent/store/agent.store.ts:
--------------------------------------------------------------------------------
1 | import { makeStore } from '@microphi/store';
2 | import { EntityStore } from '../../../entity';
3 | import { Agent } from '../agent.model';
4 | import { AgentService } from '../service/agent.service';
5 | import { AgentState } from './agent.state';
6 | import { AgentActions } from './agent.actions';
7 | import { Injectable } from '@angular/core';
8 |
9 | @Injectable({
10 | providedIn: 'root'
11 | })
12 | export class AgentStore extends EntityStore implements makeStore {
13 |
14 | constructor(protected service: AgentService) {
15 | super({
16 | list: [],
17 | total: 0,
18 | });
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/observability_ui/libs/core/src/lib/entities/index.ts:
--------------------------------------------------------------------------------
1 | export * from './agent/agent.model';
2 | export * from './agent/service/agent.service';
3 | export * from './agent/store/agent.actions';
4 | export * from './agent/store/agent.state';
5 | export * from './agent/store/agent.store';
6 |
--------------------------------------------------------------------------------
/observability_ui/libs/core/src/lib/entity/entity-type.ts:
--------------------------------------------------------------------------------
1 | export enum EntityType {
2 | User = 'User',
3 | Company = 'Company',
4 | Organization = 'Organization',
5 | Project = 'Project',
6 | Event = 'Event',
7 | Run = 'Run',
8 | Pipeline = 'Pipeline',
9 | Task = 'Task',
10 | Rule = 'Rule',
11 | Journey = 'Journey',
12 | Instance = 'Instance',
13 | Component = 'Component',
14 | ServiceKey = 'ServiceAccountKey',
15 | Dashboards = 'Dashboards',
16 | Agent = 'Agent',
17 | ProjectAlertSettings = 'ProjectAlertSettings',
18 | }
19 |
--------------------------------------------------------------------------------
/observability_ui/libs/core/src/lib/entity/index.ts:
--------------------------------------------------------------------------------
1 |
2 | export * from './entity.service';
3 | export * from './entity.store';
4 | export * from './entity.model';
5 | export * from './read-only-rest-api.service';
6 | export { EntityType } from './entity-type';
7 | export { entityDefaultUrlMappings } from './entity-default-url.mappings';
8 |
9 |
--------------------------------------------------------------------------------
/observability_ui/libs/core/src/lib/guards/no-auth/no-auth.guard.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@angular/core';
2 | import { UrlTree } from '@angular/router';
3 | import { map } from 'rxjs/operators';
4 | import { Observable } from 'rxjs';
5 | import { SessionService } from '../../services/auth/session.service';
6 |
7 | @Injectable({ providedIn: 'root' })
8 | export class NoAuthGuard {
9 | constructor(private sessionService: SessionService) {}
10 |
11 | canActivate(): Observable {
12 | return this.sessionService.isLoggedIn$.pipe(
13 | map((isLoggedIn) => !isLoggedIn),
14 | );
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/observability_ui/libs/core/src/lib/guards/reset-stores.guard.ts:
--------------------------------------------------------------------------------
1 | import { CanActivateFn } from "@angular/router";
2 | import { EntityStore } from "../entity";
3 | import { inject } from "@angular/core";
4 |
5 | export function resetStores(...stores: Array>): CanActivateFn {
6 | return () => {
7 | for (const storeType of stores) {
8 | inject(storeType).dispatch('reset');
9 | }
10 | return true;
11 | };
12 | }
--------------------------------------------------------------------------------
/observability_ui/libs/core/src/lib/interceptors/index.ts:
--------------------------------------------------------------------------------
1 | export * from './base-http.interceptor';
2 | export * from './filter-params.interceptor';
3 |
--------------------------------------------------------------------------------
/observability_ui/libs/core/src/lib/models/alert.model.ts:
--------------------------------------------------------------------------------
1 | export interface Alert {
2 | /**
3 | * Where `Type` must be an enum with possible types such as
4 | *
5 | * export enum AlertType {
6 | * lateStart = 'LATE_START',
7 | * lateEnd = 'LATE_END',
8 | * }
9 | */
10 |
11 | id: string;
12 | run: string;
13 | level: AlertLevel;
14 | type: AlertType;
15 | name?: string;
16 | description: string;
17 | created_on: string;
18 | }
19 |
20 | export type AlertLevel = 'WARNING' | 'ERROR';
21 |
--------------------------------------------------------------------------------
/observability_ui/libs/core/src/lib/models/index.ts:
--------------------------------------------------------------------------------
1 | export * from './alert.model';
2 | export * from './runs.model';
3 | export * from './component.model';
4 | export * from './event.model';
5 | export * from './integrations.model';
6 | export * from './journey.model';
7 | export * from './instance.model';
8 |
--------------------------------------------------------------------------------
/observability_ui/libs/core/src/lib/models/integrations.model.ts:
--------------------------------------------------------------------------------
1 | export interface IntegrationV1 {
2 | integration_name: 'TESTGEN';
3 | }
4 |
5 | export interface TestgenTestOutcomeIntegrationV1 extends IntegrationV1 {
6 | integration_name: 'TESTGEN';
7 | table: string;
8 | columns?: string[];
9 | test_suite: string;
10 | version: number;
11 | test_parameters: Parameter[];
12 | }
13 |
14 | interface Parameter {
15 | name: string;
16 | value: string | number;
17 | }
18 |
--------------------------------------------------------------------------------
/observability_ui/libs/core/src/lib/services/auth/auth.model.ts:
--------------------------------------------------------------------------------
1 | export const cookieKeys = {
2 | token: 'access_token',
3 | };
4 | export const cookiePath = '/';
5 |
6 | export const localStorageKeys = {
7 | loginRedirect: 'login_redirect',
8 | };
9 |
10 | export enum AuthProviderType {
11 | Auth0 = 'auth0',
12 | OpenID = 'openId',
13 | }
14 |
15 | export interface AuthProvider {
16 | type: AuthProviderType;
17 | is_sso: boolean;
18 | }
19 |
20 | export interface Auth0AuthProvider extends AuthProvider {
21 | type: AuthProviderType.Auth0;
22 | }
23 |
24 | export interface OpenIDAuthProvider extends AuthProvider {
25 | type: AuthProviderType.OpenID;
26 | domain: string;
27 | client_id: string;
28 | client_secret: string;
29 | }
30 |
--------------------------------------------------------------------------------
/observability_ui/libs/core/src/lib/services/index.ts:
--------------------------------------------------------------------------------
1 | export * from './user/user.model';
2 | export * from './user/user.service';
3 |
4 | export * from './auth/auth.model';
5 | export * from './auth/session.service';
6 |
7 | export * from './company/company.model';
8 | export * from './company/company.service';
9 |
10 |
11 | export * from './organization/organization.model';
12 | export * from './organization/organization.service';
13 |
14 | // Projects
15 | export * from './project/project.model';
16 | export * from './project/project.service';
17 | export * from './project/project.store';
18 |
--------------------------------------------------------------------------------
/observability_ui/libs/core/src/lib/services/organization/organization.model.ts:
--------------------------------------------------------------------------------
1 | import { Entity } from '../../entity';
2 |
3 | export interface Organization extends Entity {
4 | company: string;
5 | }
6 |
--------------------------------------------------------------------------------
/observability_ui/libs/core/src/lib/services/organization/organization.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@angular/core';
2 | import { Organization } from './organization.model';
3 | import { EntityService, EntityType } from '../../entity';
4 |
5 | @Injectable({ providedIn: 'root' })
6 | export class OrganizationService extends EntityService {
7 | protected override baseEntity = EntityType.Organization;
8 | protected override parentEntity = EntityType.Company;
9 | }
10 |
--------------------------------------------------------------------------------
/observability_ui/libs/core/src/lib/services/user/user.model.ts:
--------------------------------------------------------------------------------
1 | import { Entity, EntityType, Role } from '../../entity';
2 | import { Company } from '../company/company.model';
3 |
4 | export interface User extends Entity {
5 | email: string;
6 | job_title: string;
7 | job_function: string;
8 | primary_company: string;
9 | admin: boolean;
10 | roles?: UserRoleAssignment[];
11 | }
12 |
13 | export interface ExpandedUser extends Omit {
14 | created_by: User;
15 | primary_company: Company;
16 | }
17 |
18 | export interface UserRoleAssignment extends Role {
19 | assignments: { [entityType in EntityType]?: number[] };
20 | }
21 |
--------------------------------------------------------------------------------
/observability_ui/libs/core/src/lib/services/user/user.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@angular/core';
2 | import { User } from './user.model';
3 | import { Observable } from 'rxjs';
4 | import { EntityListResponse, EntityService, EntityType } from '../../entity';
5 |
6 | @Injectable({
7 | providedIn: 'root'
8 | })
9 | export class UserService extends EntityService {
10 |
11 | override baseEntity = EntityType.User;
12 |
13 | getUsersByCompany(companyId: number): Observable> {
14 | return this.http.get>(`${this.apiBaseUrl}/${this.prefix}/v1/companies/${companyId}/users`);
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/observability_ui/libs/core/src/lib/templating/index.ts:
--------------------------------------------------------------------------------
1 | export * from './abstract-templating.directive';
2 |
--------------------------------------------------------------------------------
/observability_ui/libs/core/src/lib/utilities/tools.utilities.spec.ts:
--------------------------------------------------------------------------------
1 | import { listEnvVariableFormatter } from './tools.utilities';
2 |
3 | describe('listEnvVariableFormatter', () => {
4 | it('should generate list value correctly for script', () => {
5 | const testCases = [
6 | { input: '', output: '[]' },
7 | { input: null, output: '[]' },
8 | { input: ' ', output: '[]' },
9 | { input: 'pip', output: '[\\"pip\\"]' },
10 | { input: 'pip1,pip2', output: '[\\"pip1\\",\\"pip2\\"]' },
11 | { input: ' pip1 , pip2 ', output: '[\\"pip1\\",\\"pip2\\"]' },
12 | ];
13 | testCases.forEach(({ input, output }) => {
14 | expect(listEnvVariableFormatter(input)).toEqual(output);
15 | });
16 | });
17 | });
18 |
--------------------------------------------------------------------------------
/observability_ui/libs/core/src/lib/utilities/tools.utilities.ts:
--------------------------------------------------------------------------------
1 | export function listEnvVariableFormatter(value: string | null): string {
2 | const trimmed = value?.trim();
3 | if (!trimmed) {
4 | return '[]';
5 | }
6 | const trimmedArray = trimmed.split(',').map(item => item?.trim());
7 | return JSON.stringify(JSON.stringify(trimmedArray)).slice(1, -1);
8 | }
9 |
--------------------------------------------------------------------------------
/observability_ui/libs/core/src/test-setup.ts:
--------------------------------------------------------------------------------
1 | import 'jest-preset-angular/setup-jest';
2 |
--------------------------------------------------------------------------------
/observability_ui/libs/core/tsconfig.lib.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../../dist/out-tsc",
5 | "declaration": true,
6 | "declarationMap": true,
7 | "inlineSources": true,
8 | "types": []
9 | },
10 | "exclude": [
11 | "src/test-setup.ts",
12 | "**/*.spec.ts",
13 | "**/*.test.ts",
14 | "src/testing/*.ts",
15 | "jest.config.ts"
16 | ],
17 | "include": ["**/*.ts"]
18 | }
19 |
--------------------------------------------------------------------------------
/observability_ui/libs/core/tsconfig.spec.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../../dist/out-tsc",
5 | "module": "commonjs",
6 | "types": ["jest", "node"],
7 | "target": "es2016"
8 | },
9 | "files": ["src/test-setup.ts"],
10 | "include": [
11 | "**/*.test.ts",
12 | "**/*.spec.ts",
13 | "**/*.d.ts",
14 | "src/testing/*.ts",
15 | "jest.config.ts"
16 | ]
17 | }
18 |
--------------------------------------------------------------------------------
/observability_ui/libs/translate/README.md:
--------------------------------------------------------------------------------
1 | # translate
2 |
3 | This library was generated with [Nx](https://nx.dev).
4 |
5 | ## Running unit tests
6 |
7 | Run `nx test translate` to execute the unit tests.
8 |
--------------------------------------------------------------------------------
/observability_ui/libs/translate/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@observability/translate",
3 | "version": "2.0.0",
4 | "description": "this is the core lib of observability mfe setup",
5 | "license": "MIT"
6 | }
7 |
--------------------------------------------------------------------------------
/observability_ui/libs/translate/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './lib/translation.module';
2 | export * from './lib/translation.service';
3 | export * from './lib/translate.pipe';
4 |
5 | export * from './lib/translate.pipe.mock';
6 |
--------------------------------------------------------------------------------
/observability_ui/libs/translate/src/lib/translate.pipe.mock.ts:
--------------------------------------------------------------------------------
1 | import { Pipe, PipeTransform } from '@angular/core';
2 |
3 | @Pipe({
4 | name: 'translate',
5 | })
6 | export class TranslatePipeMock implements PipeTransform {
7 | transform(key: string): string {
8 | return key;
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/observability_ui/libs/translate/src/lib/translate.pipe.ts:
--------------------------------------------------------------------------------
1 | import { Pipe, PipeTransform } from '@angular/core';
2 | import { TranslationService } from './translation.service';
3 |
4 | @Pipe({
5 | name: 'translate',
6 | })
7 | export class TranslatePipe implements PipeTransform {
8 | constructor(private translationService: TranslationService) {
9 | }
10 |
11 | public transform(key: string, params?: object, defaultTo?: string): string {
12 | const translation = this.translationService.translate(key, params);
13 | if (translation === key && defaultTo) {
14 | return defaultTo;
15 | }
16 | return translation;
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/observability_ui/libs/translate/src/test-setup.ts:
--------------------------------------------------------------------------------
1 | import 'jest-preset-angular/setup-jest';
2 |
--------------------------------------------------------------------------------
/observability_ui/libs/translate/tsconfig.lib.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../../dist/out-tsc",
5 | "declaration": true,
6 | "declarationMap": true,
7 | "inlineSources": true,
8 | "types": []
9 | },
10 | "exclude": [
11 | "src/test-setup.ts",
12 | "**/*.spec.ts",
13 | "**/*.test.ts",
14 | "jest.config.ts"
15 | ],
16 | "include": ["**/*.ts"]
17 | }
18 |
--------------------------------------------------------------------------------
/observability_ui/libs/translate/tsconfig.spec.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../../dist/out-tsc",
5 | "module": "commonjs",
6 | "types": ["jest", "node"],
7 | "target": "es2016"
8 | },
9 | "files": ["src/test-setup.ts"],
10 | "include": ["**/*.test.ts", "**/*.spec.ts", "**/*.d.ts", "jest.config.ts"]
11 | }
12 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/README.md:
--------------------------------------------------------------------------------
1 | # ui
2 |
3 | This library was generated with [Nx](https://nx.dev).
4 |
5 | ## Running unit tests
6 |
7 | Run `nx test ui` to execute the unit tests.
8 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@observability/ui",
3 | "version": "2.0.0",
4 | "description": "this is the core lib of observability mfe setup",
5 | "license": "MIT",
6 | "scripts": {
7 | "make:linkable": "yarn link"
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/breadcrumb/breadcrumb.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 | {{item.label}}
7 |
8 |
9 |
11 | {{item.label}}
12 |
13 |
14 |
16 | navigate_next
17 |
18 |
19 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/breadcrumb/breadcrumb.component.scss:
--------------------------------------------------------------------------------
1 | @import '../../../styles/mixins';
2 |
3 | :host {
4 | @include flex-row($justify: flex-start);
5 | @include font-style(caption, secondary);
6 |
7 | line-height: 14px;
8 | }
9 |
10 | .breadcrumb__link {
11 | @include link(secondary);
12 | }
13 |
14 | .breadcrumb__icon {
15 | @include icon-size(16px);
16 | }
17 |
18 | .breadcrumb__item,
19 | .breadcrumb__link {
20 | &:last-child {
21 | @include font-color(primary);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/breadcrumb/breadcrumb.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { TestBed, ComponentFixture } from '@angular/core/testing';
2 | import { BreadcrumbComponent } from './breadcrumb.component';
3 |
4 | describe('Breadcrumb Component', () => {
5 | let fixture: ComponentFixture;
6 | let component: BreadcrumbComponent;
7 |
8 | beforeEach(() => {
9 | TestBed.configureTestingModule({
10 | imports: [],
11 | declarations: [],
12 | providers: [],
13 | });
14 |
15 | fixture = TestBed.createComponent(BreadcrumbComponent);
16 | component = fixture.componentInstance;
17 | });
18 |
19 | it('should exist', () => {
20 | expect(component).toBeDefined();
21 | });
22 | });
23 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/breadcrumb/breadcrumb.component.ts:
--------------------------------------------------------------------------------
1 | import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
2 | import { BreadcrumbItem } from './breadcrumb.model';
3 |
4 |
5 | @Component({
6 | selector: 'breadcrumb',
7 | templateUrl: 'breadcrumb.component.html',
8 | styleUrls: [ 'breadcrumb.component.scss' ],
9 | changeDetection: ChangeDetectionStrategy.OnPush,
10 | })
11 | export class BreadcrumbComponent {
12 |
13 | @Input() items!: BreadcrumbItem[];
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/breadcrumb/breadcrumb.model.ts:
--------------------------------------------------------------------------------
1 | export interface BreadcrumbItem {
2 | label: string;
3 | link?: string | any[];
4 | }
5 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/breadcrumb/breadcrumb.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { CommonModule } from '@angular/common';
3 | import { MatIconModule } from '@angular/material/icon';
4 | import { RouterModule } from '@angular/router';
5 | import { BreadcrumbComponent } from './breadcrumb.component';
6 |
7 |
8 | @NgModule({
9 | imports: [
10 | CommonModule,
11 | MatIconModule,
12 | RouterModule,
13 | ],
14 | exports: [ BreadcrumbComponent ],
15 | declarations: [ BreadcrumbComponent ],
16 | providers: [],
17 | })
18 | export class BreadcrumbModule {
19 | }
20 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/code-snippet/code-snippet.component.html:
--------------------------------------------------------------------------------
1 |
14 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/dag/dag-edge.directive.ts:
--------------------------------------------------------------------------------
1 | import { Directive, Input } from '@angular/core';
2 | import { DagEdge } from './dag.model';
3 |
4 | @Directive({
5 | selector: 'dag-edge',
6 | })
7 | export class DagEdgeDirective implements DagEdge {
8 | @Input() public id!: string;
9 | @Input() public fromNode!: string;
10 | @Input() public toNode!: string;
11 |
12 | public path: string = '';
13 | public selected: boolean = false;
14 | public points: Array<{x: number; y: number}> = [];
15 | }
16 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/dag/dag-legend.directive.ts:
--------------------------------------------------------------------------------
1 | import { Directive } from '@angular/core';
2 |
3 | @Directive({
4 | selector: '[dagLegend]',
5 | })
6 | export class DagLegendDirective {}
7 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/dag/dag.model.ts:
--------------------------------------------------------------------------------
1 | export enum DagOrientation {
2 | Horizontal = 'HORIZONTAL',
3 | Vertical = 'VERTICAL',
4 | }
5 |
6 | export interface DagEdge {
7 | path: string;
8 | points: Array<{x: number; y: number}>;
9 | }
10 |
11 | export interface DraggedDagEdge extends DagEdge {
12 | offset: { x: number, y: number };
13 | sourceNodeId: string;
14 | }
15 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/dag/dag.translation.ts:
--------------------------------------------------------------------------------
1 |
2 | export const dagTranslations = {
3 | dag: {
4 | renderingError: 'Unable to render the graph',
5 | errorAction: 'Refresh',
6 |
7 | zoom: {
8 | in: 'Zoom In',
9 | out: 'Zoom Out',
10 | toFit: 'Zoom to Fit',
11 | },
12 |
13 | arrange: {
14 | leftToRight: 'Align Left-Right',
15 | topToBottom: 'Align Top-Bottom',
16 | },
17 |
18 | legend: {
19 | show: 'Show legend',
20 | hide: 'Hide legend',
21 | },
22 | },
23 | };
24 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/dag/index.ts:
--------------------------------------------------------------------------------
1 | export * from './dag.module';
2 |
3 | export * from './dag.component';
4 |
5 | export * from './dag-node.directive';
6 | export * from './dag-edge.directive';
7 | export * from './dag-legend.directive';
8 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/details-header/details-header.component.html:
--------------------------------------------------------------------------------
1 |
2 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/details-header/details-header.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, Input } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'details-header',
5 | templateUrl: 'details-header.component.html',
6 | styleUrls: [ 'details-header.component.scss' ],
7 | })
8 | export class DetailsHeaderComponent {
9 | @Input() title!: string;
10 | @Input() subTitle!: string;
11 | @Input() backLink!: string | string[];
12 | @Input() backLinkTitle!: string;
13 | }
14 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/details-header/index.ts:
--------------------------------------------------------------------------------
1 | export * from './details-header.module';
2 | export * from './details-header.component';
3 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/directives/dynamic-component/dynamic-component.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { DynamicComponentOutletDirective } from './dynamic-component-outlet.directive';
3 |
4 | @NgModule({
5 | imports: [],
6 | exports: [
7 | DynamicComponentOutletDirective,
8 | ],
9 | declarations: [
10 | DynamicComponentOutletDirective,
11 | ],
12 | providers: [],
13 | })
14 | export class DynamicComponentModule {
15 | }
16 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/directives/dynamic-component/index.ts:
--------------------------------------------------------------------------------
1 | export * from './dynamic-component.module';
2 | export * from './dynamic-component-outlet.directive';
3 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/directives/index.ts:
--------------------------------------------------------------------------------
1 | export * from './bind-query-params/bind-query-params.module';
2 | export * from './bind-query-params/to-mat-paginator/bind-query-params-mat-paginator.directive';
3 | export * from './bind-query-params/to-mat-sort/bind-query-params-mat-sort.directive';
4 | export * from './bind-query-params/to-mat-tab/bind-query-params-mat-tab.directive';
5 |
6 | export * from './dynamic-component/dynamic-component.module';
7 | export * from './dynamic-component/dynamic-component-outlet.directive';
8 |
9 | export * from './click-confirm/click-confirm.directive';
10 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/dk-tooltip/click-listener.service.ts:
--------------------------------------------------------------------------------
1 | import { Inject, Injectable } from '@angular/core';
2 | import { Observable, Subject } from 'rxjs';
3 | import { DOCUMENT } from '@angular/common';
4 |
5 | @Injectable({
6 | providedIn: 'root',
7 | })
8 | export class ClickListenerService {
9 |
10 | private _onClick: Subject = new Subject();
11 |
12 | constructor(@Inject(DOCUMENT) private document: Document) {
13 | this.document.addEventListener('click', this.clicked.bind(this));
14 | }
15 |
16 | get onClick(): Observable {
17 | return this._onClick.asObservable();
18 | }
19 |
20 | private clicked($event: MouseEvent) {
21 | this._onClick.next($event);
22 | }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/dk-tooltip/index.ts:
--------------------------------------------------------------------------------
1 | export * from './click-listener.service';
2 | export * from './dk-tooltip.component';
3 | export * from './dk-tooltip.directive';
4 | export * from './dk-tooltip.module';
5 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/dots-chart/dot-template.directive.ts:
--------------------------------------------------------------------------------
1 | /* istanbul ignore file */
2 |
3 | import { Directive, Input, TemplateRef } from '@angular/core';
4 |
5 | @Directive({
6 | selector: '[dotTpl]',
7 | standalone: true,
8 | })
9 | export class DotTemplateDirective {
10 | @Input('dotTpl') value!: object;
11 |
12 | constructor(public template: TemplateRef) {}
13 | }
14 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/dots-chart/dot.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { ComponentFixture, TestBed } from '@angular/core/testing';
2 | import { DotComponent } from './dot.component';
3 |
4 | describe('DotComponent', () => {
5 | let fixture: ComponentFixture;
6 | let component: DotComponent;
7 |
8 | beforeEach(async () => {
9 | TestBed.configureTestingModule({
10 | imports: [
11 | DotComponent,
12 | ],
13 | });
14 |
15 | fixture = TestBed.createComponent(DotComponent);
16 | component = fixture.componentInstance;
17 |
18 | fixture.detectChanges();
19 | });
20 |
21 | it('should create', () => {
22 | expect(component).toBeDefined();
23 | });
24 | });
25 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/dots-chart/dot.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, HostBinding, Input } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'dot',
5 | template: ``,
6 | styleUrls: ['dot.component.scss'],
7 | standalone: true,
8 | })
9 | export class DotComponent {
10 | @HostBinding('class') @Input() status!: 'ACTIVE' | 'COMPLETED' | 'WARNING' | 'ERROR' | 'UPCOMING';
11 | @HostBinding('class.has-runs') @Input() hasRuns!: boolean;
12 | }
13 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/dots-chart/drill-in.directive.ts:
--------------------------------------------------------------------------------
1 | /* istanbul ignore file */
2 |
3 | import { Directive, TemplateRef } from '@angular/core';
4 |
5 | @Directive({
6 | selector: '[drillInTemplate]',
7 | standalone: true,
8 | })
9 | export class DrillInTemplateDirective {
10 | constructor(public template: TemplateRef) {}
11 | }
12 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/duration/duration.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, Input, OnInit } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'duration',
5 | template: `{{ (start|date:dateFormat)|duration:(end|date:dateFormat)}}`
6 | })
7 | export class DurationComponent implements OnInit {
8 |
9 | @Input() start!: string;
10 | @Input() end!: string;
11 |
12 | dateFormat = 'EEEE, MMMM d, y, h:mm:ss a zzzz';
13 |
14 | ngOnInit() {
15 | if (!this.end) {
16 | this.end = new Date().getTime().toString();
17 | }
18 | }
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/duration/duration.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { DurationPipe } from './duration.pipe';
3 | import { DurationComponent } from './duration.component';
4 | import { CommonModule } from '@angular/common';
5 |
6 | @NgModule({
7 | imports: [ CommonModule ],
8 | declarations: [ DurationPipe, DurationComponent ],
9 | exports: [ DurationPipe, DurationComponent ]
10 | })
11 | export class DurationModule {}
12 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/duration/index.ts:
--------------------------------------------------------------------------------
1 | export * from './duration.module';
2 | export * from './duration.pipe';
3 | export * from './duration.component';
4 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/empty-state-setup/empty-state-setup.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
14 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/empty-state-setup/empty-state-setup.component.ts:
--------------------------------------------------------------------------------
1 | import { Component } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'empty-state-setup',
5 | templateUrl: './empty-state-setup.component.html',
6 | styleUrls: ['./empty-state-setup.component.scss'],
7 | standalone: true,
8 | })
9 | export class EmptyStateSetupComponent {}
10 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/entity/active-status-chip/active-status-chip.component.html:
--------------------------------------------------------------------------------
1 |
2 | {{ (active ? 'active' : 'inactive') | translate }}
3 |
4 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/entity/active-status-chip/active-status-chip.component.ts:
--------------------------------------------------------------------------------
1 | import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
2 |
3 |
4 | @Component({
5 | selector: 'active-status-chip',
6 | templateUrl: 'active-status-chip.component.html',
7 | changeDetection: ChangeDetectionStrategy.OnPush,
8 | })
9 | export class ActiveStatusChipComponent {
10 |
11 | @Input() active!: boolean;
12 | }
13 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/entity/entity-list-placeholder/entity-list-placeholder.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 |
9 | {{ (hasFilters ? 'noEntitiesForFilters' : 'noEntitiesFound') | translate:{entity: entity} }}
10 |
11 |
12 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/entity/entity-list-placeholder/entity-list-placeholder.component.scss:
--------------------------------------------------------------------------------
1 | @use "@observability/ui/styles/mixins" as mixins;
2 | @import "@observability/ui/styles/variables";
3 |
4 |
5 | $placeholder-height: 200px;
6 |
7 | div {
8 | @include mixins.font-style(subheader, secondary);
9 | @include mixins.flex-row($justify: center, $align: center);
10 |
11 | height: $placeholder-height;
12 | border-bottom: $border;
13 | }
14 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/entity/entity-list-placeholder/entity-list-placeholder.component.ts:
--------------------------------------------------------------------------------
1 | import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
2 |
3 |
4 | @Component({
5 | selector: 'entity-list-placeholder',
6 | styleUrls: [ 'entity-list-placeholder.component.scss' ],
7 | templateUrl: 'entity-list-placeholder.component.html',
8 | changeDetection: ChangeDetectionStrategy.OnPush,
9 | })
10 | export class EntityListPlaceholderComponent {
11 |
12 | @Input() entity!: string;
13 | @Input() loading!: boolean;
14 | @Input() total!: number;
15 | @Input() hasFilters!: boolean;
16 | }
17 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/entity/index.ts:
--------------------------------------------------------------------------------
1 | export * from './entity.module';
2 |
3 | export * from './entity-list-placeholder/entity-list-placeholder.component';
4 |
5 | export * from './active-status-chip/active-status-chip.component';
6 |
7 | export * from './nullify-pending/nullify-pending.pipe';
8 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/entity/nullify-pending/nullify-pending.pipe.ts:
--------------------------------------------------------------------------------
1 | import { Pipe, PipeTransform } from '@angular/core';
2 |
3 | @Pipe({name: 'nullifyPending'})
4 | export class NullifyPendingPipe implements PipeTransform {
5 |
6 | transform(value: T) {
7 | if (typeof value === 'string') {
8 | return value.startsWith('_DK_PENDING_') ? null : value;
9 | }
10 | return value;
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/expansion-panel/expansion-panel-content/expansion-panel-content.component.ts:
--------------------------------------------------------------------------------
1 | import { Component } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'expansion-panel-content',
5 | template: ``,
6 | })
7 | export class ExpansionPanelContentComponent {}
8 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/expansion-panel/expansion-panel-title/expansion-panel-title.component.ts:
--------------------------------------------------------------------------------
1 | import { Component } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'expansion-panel-title',
5 | template: ``
6 | })
7 | export class ExpansionPanelTitleComponent {}
8 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/expansion-panel/expansion-panel/expansion-panel.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{open ? 'arrow_drop_down' : 'arrow_right'}}
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/expansion-panel/expansion-panel/expansion-panel.component.scss:
--------------------------------------------------------------------------------
1 | :host {
2 | display: flex;
3 | flex-direction: row;
4 | }
5 |
6 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/expansion-panel/expansion-panel/expansion-panel.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, Input } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'expansion-panel',
5 | templateUrl: 'expansion-panel.component.html' ,
6 | styleUrls: [ 'expansion-panel.component.scss' ],
7 | })
8 | export class ExpansionPanelComponent {
9 | @Input() open: boolean = false;
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/expansion-panel/index.ts:
--------------------------------------------------------------------------------
1 | export * from './expansion-panel.module';
2 | export * from './expansion-panel/expansion-panel.component';
3 |
4 | export * from './expansion-panel-title/expansion-panel-title.component';
5 | export * from './expansion-panel-content/expansion-panel-content.component';
6 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/fields/checkbox-field/checkbox-field.component.html:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 | {{label}}
8 |
9 |
10 |
11 |
12 |
13 |
14 |
16 | help_outline
19 |
20 |
21 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/fields/checkbox-field/checkbox-field.component.scss:
--------------------------------------------------------------------------------
1 | @import '@observability/ui/styles/fields';
2 |
3 |
4 | :host {
5 | @include field;
6 |
7 | justify-content: flex-start;
8 | margin: $field-margin-top 0 $field-margin-bottom;
9 |
10 | &.form-field--no-margin-top {
11 | margin-top: 0;
12 | }
13 |
14 | &.form-field--indent {
15 | padding-left: 28px;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/fields/schedule-field/schedule.pipe.ts:
--------------------------------------------------------------------------------
1 | import { Pipe, PipeTransform } from '@angular/core';
2 | import cronstrue from 'cronstrue';
3 | import { Schedule } from '@observability-ui/core';
4 |
5 | @Pipe({
6 | name: 'schedule',
7 | })
8 | export class SchedulePipe implements PipeTransform {
9 | public transform(schedule?: Schedule | null): string {
10 | if (!schedule?.schedule) {
11 | return '...';
12 | }
13 |
14 | return `${cronstrue.toString(schedule.schedule).replace('At ', '').toLowerCase()}${schedule.timezone ? ' (' + schedule.timezone + ')' : ''}`;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/fields/text-field/text-field-error.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, Input, TemplateRef, ViewChild } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'text-field-error',
5 | template: `
6 |
7 |
8 |
9 | `
10 | })
11 | export class TextFieldErrorComponent {
12 |
13 | @Input() type!: string;
14 |
15 | @ViewChild(TemplateRef, { static: true }) template!: TemplateRef;
16 | }
17 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/fields/text-field/text-field.component.scss:
--------------------------------------------------------------------------------
1 | @use '@observability/ui/styles/mixins' as mixins;
2 |
3 | :host {
4 | display: flex;
5 | flex-direction: column;
6 | }
7 |
8 | mat-icon {
9 | @include mixins.font-color(secondary);
10 |
11 | height: 1em;
12 | font-size: 100% !important;
13 | }
14 |
15 | .search-icon {
16 | margin-right: 4px;
17 | }
18 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/fields/timespan-field/timespan-field.component.scss:
--------------------------------------------------------------------------------
1 | .nowrap {
2 | white-space: nowrap;
3 | }
4 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/fields/timespan-field/timespan.pipe.ts:
--------------------------------------------------------------------------------
1 | import { Pipe, PipeTransform } from '@angular/core';
2 |
3 | @Pipe({
4 | name: 'timespan'
5 | })
6 |
7 | export class TimespanPipe implements PipeTransform {
8 | transform(value: number): string {
9 | if (Number.isInteger(value / 86400)) {
10 | return `${value / 86400} days`;
11 | } else if (Number.isInteger(value / 3600)) {
12 | return `${value / 3600} hours`;
13 | }
14 |
15 | return `${value / 60} minutes`;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/fields/timespan-field/timespan.translation.ts:
--------------------------------------------------------------------------------
1 | export const timespanTranslation = {
2 | days: 'days',
3 | hours: 'hours',
4 | minutes: 'minutes'
5 | };
6 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/gantt-chart/gantt-chart.model.ts:
--------------------------------------------------------------------------------
1 | import { GanttBarDirective } from './gantt-bar.directive';
2 |
3 | export interface Position {
4 | offset: number;
5 | duration: number;
6 | }
7 |
8 | export interface GanttTaskGroup {
9 | id: string;
10 | label: string;
11 | tasks: GanttBarDirective[];
12 | children: GanttTaskGroup[];
13 | start_type: 'DEFAULT' | 'SCHEDULED' | 'BATCH' | 'PAYLOAD',
14 | payload_key?: string;
15 | }
16 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/gantt-chart/gantt-chart.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { CommonModule } from '@angular/common';
3 | import { GanttChartComponent } from './gantt-chart.component';
4 | import { GanttTaskComponent } from './gantt-task.component';
5 | import { GanttBarDirective } from './gantt-bar.directive';
6 | import { GanttLabelDirective } from './gantt-label.directive';
7 |
8 | @NgModule({
9 | imports: [
10 | CommonModule,
11 | ],
12 | declarations: [ GanttChartComponent, GanttTaskComponent, GanttBarDirective, GanttLabelDirective ],
13 | exports: [ GanttChartComponent, GanttTaskComponent, GanttBarDirective, GanttLabelDirective ]
14 | })
15 | export class GanttChartModule {
16 | }
17 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/gantt-chart/gantt-label.directive.ts:
--------------------------------------------------------------------------------
1 | /* istanbul ignore file */
2 |
3 | import { Directive, TemplateRef } from '@angular/core';
4 |
5 | @Directive({
6 | selector: '[ganttLabel]',
7 | })
8 | export class GanttLabelDirective {
9 | constructor(
10 | public template: TemplateRef,
11 | ) {}
12 | }
13 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/is-today/is-today.pipe.ts:
--------------------------------------------------------------------------------
1 | import { Pipe, PipeTransform } from '@angular/core';
2 | import { formatDate } from '@angular/common';
3 |
4 | @Pipe({
5 | name: 'isToday',
6 | standalone: true
7 | })
8 | export class IsTodayPipe implements PipeTransform {
9 | transform(value: any): any {
10 | const today = formatDate(new Date(), 'yyyy.MM.dd', 'en');
11 | const date = formatDate(value, 'yyyy.MM.dd', 'en');
12 |
13 | return today === date;
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/labeled-menu/index.ts:
--------------------------------------------------------------------------------
1 | export * from './labeled-menu.module';
2 | export * from './labeled-menu.component';
3 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/labeled-menu/labeled-menu.component.html:
--------------------------------------------------------------------------------
1 |
13 |
17 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/labeled-menu/labeled-menu.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, Input } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'labeled-menu',
5 | templateUrl: 'labeled-menu.component.html',
6 | styleUrls: [ 'labeled-menu.component.scss' ],
7 | })
8 | export class LabeledMenuComponent {
9 |
10 | @Input()
11 | public label!: string;
12 |
13 | @Input()
14 | public showDropDownArrow!: boolean;
15 |
16 | @Input()
17 | public id!: string;
18 |
19 | @Input()
20 | public disabled!: boolean;
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/labeled-menu/labeled-menu.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { MatButtonModule } from '@angular/material/button';
3 | import { MatMenuModule } from '@angular/material/menu';
4 | import { MatIconModule } from '@angular/material/icon';
5 | import { CommonModule } from '@angular/common';
6 | import { LabeledMenuComponent } from './labeled-menu.component';
7 |
8 |
9 | @NgModule({
10 | imports: [
11 | MatButtonModule,
12 | MatMenuModule,
13 | MatIconModule,
14 | CommonModule,
15 | ],
16 | exports: [
17 | LabeledMenuComponent,
18 | ],
19 | declarations: [
20 | LabeledMenuComponent,
21 | ],
22 | providers: [],
23 | })
24 | export class LabeledMenuModule {
25 | }
26 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/mat-card-edit/mat-card-edit.component.scss:
--------------------------------------------------------------------------------
1 | @use '@observability/ui/styles/variables' as variables;
2 | @use '@observability/ui/styles/mixins' as mixins;
3 |
4 | .title {
5 | @include mixins.font-style($style: menu);
6 | }
7 |
8 | .edit-icon {
9 | @include mixins.icon-size(16px);
10 | @include mixins.font-color(secondary);
11 |
12 | position: absolute;
13 | top: variables.$space-sm;
14 | right: variables.$space-sm;
15 | cursor: pointer;
16 | }
17 |
18 | mat-card.editing {
19 | padding-bottom: 8px ;
20 | }
21 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/metadata-viewer/index.ts:
--------------------------------------------------------------------------------
1 | export * from './metadata-viewer.module';
2 | export * from './metadata-viewer.component';
3 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/pipes/get-integration/get-integration.pipe.ts:
--------------------------------------------------------------------------------
1 | import { Pipe, PipeTransform } from '@angular/core';
2 | import { IntegrationV1 } from '@observability-ui/core';
3 |
4 | @Pipe({
5 | name: 'getIntegration',
6 | pure: true,
7 | standalone: true,
8 | })
9 | export class GetIngrationPipe implements PipeTransform {
10 | transform(integrations: IntegrationV1[], name: IntegrationV1['integration_name']): IntegrationV1 | undefined {
11 | if (!integrations || integrations.length <= 0 || !name) {
12 | return undefined;
13 | }
14 |
15 | return integrations.find(i => i.integration_name === name);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/pipes/humanize/humanize.pipe.ts:
--------------------------------------------------------------------------------
1 | import { Pipe, PipeTransform } from '@angular/core';
2 |
3 | @Pipe({
4 | name: 'humanize',
5 | pure: true,
6 | standalone: true,
7 | })
8 | export class HumanizePipe implements PipeTransform {
9 | transform(value: string): string {
10 | if (!value) {
11 | return '';
12 | }
13 | return this.humanize(value);
14 | }
15 |
16 | private humanize(slug: string): string {
17 | return slug.replace(/[_-]/g, ' ');
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/pipes/parseDate/parseDate.pipe.ts:
--------------------------------------------------------------------------------
1 | import { Pipe, PipeTransform } from '@angular/core';
2 | import { parseDate } from '@observability-ui/core';
3 |
4 | @Pipe({
5 | name: 'parseDate',
6 | standalone: true,
7 | })
8 |
9 | export class ParseDatePipe implements PipeTransform {
10 | transform(value: string) {
11 | return parseDate(value);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/pipes/sum/sum.pipe.ts:
--------------------------------------------------------------------------------
1 | import { Pipe, PipeTransform } from '@angular/core';
2 |
3 | @Pipe({
4 | name: 'sum',
5 | standalone: true,
6 | })
7 | export class SumPipe implements PipeTransform {
8 | transform(items: Array, key?: string) {
9 | return items.reduce((total, item) => total + this.getValue(item, key), 0);
10 | }
11 |
12 | private getValue(item: any, key?: string): number {
13 | if (!key) {
14 | return item;
15 | }
16 |
17 | let result = item;
18 | const parts = key?.trim().split(".");
19 | for (const part of parts) {
20 | result = item[part];
21 | }
22 |
23 | return result ?? 0;
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/selected-actions/selected-actions.component.scss:
--------------------------------------------------------------------------------
1 | @use '@observability/ui/styles/mixins' as mixins;
2 | @use '@observability/ui/styles/variables' as variables;
3 |
4 | :host {
5 | display: flex;
6 | }
7 |
8 | .toggle-button {
9 | background-color: variables.$gray-200;
10 |
11 | --border-radius: 0;
12 |
13 | border-radius: 4px 0 0 4px;
14 | }
15 |
16 | .actions-button {
17 | @include mixins.flex-row();
18 |
19 | --border-radius: 0;
20 |
21 | border-radius: 0 4px 4px 0;
22 |
23 | &.stand-alone {
24 | border-radius: 4px;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/table-wrapper/header-label.directive.ts:
--------------------------------------------------------------------------------
1 | import { AfterViewInit, Directive, ElementRef, Input } from '@angular/core';
2 |
3 | @Directive({
4 | selector: '[headerLabel]',
5 | })
6 | export class HeaderLabelDirective implements AfterViewInit {
7 | @Input()
8 | headerLabel!: string;
9 |
10 | textContent!: string;
11 |
12 | constructor(public elementRef: ElementRef) {
13 | }
14 |
15 | ngAfterViewInit(): void {
16 | // eslint-disable-next-line @typescript-eslint/ban-ts-comment
17 | // @ts-ignore
18 | this.textContent = this.elementRef.nativeElement.textContent.trim();
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/table-wrapper/index.ts:
--------------------------------------------------------------------------------
1 | export * from './table-wrapper.module';
2 | export * from './table-wrapper.component';
3 | export * from './table-wrapper.model';
4 | export * from './drag-disabled.directive';
5 | export * from './header-label.directive';
6 | export * from './sort-disabled.directive';
7 | export * from './toggle-disabled.directive';
8 | export * from './table-wrapper-actions.component';
9 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/table-wrapper/table-wrapper-actions.component.ts:
--------------------------------------------------------------------------------
1 | import { Component } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'table-wrapper-actions',
5 | template: ``,
6 | })
7 | export class TableWrapperActionsComponent {
8 |
9 | }
10 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/table-wrapper/table-wrapper.model.ts:
--------------------------------------------------------------------------------
1 | import { Sort } from '@angular/material/sort';
2 |
3 | export interface TableChangeEvent {
4 | pageIndex: number;
5 | pageSize: number;
6 | sort?: Sort;
7 | search: TSearch;
8 | }
9 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/table-wrapper/table-wrapper.translation.ts:
--------------------------------------------------------------------------------
1 |
2 | export const translations = {
3 | search: 'Search',
4 | refresh: 'Refresh',
5 | showHideColumns: 'Show/Hide Columns',
6 | noEntitiesFound: 'No {{entities}} found.',
7 | selected: '{{count}} item{{^count.1}}s{{/count.1}} selected'
8 | };
9 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/truncate/index.ts:
--------------------------------------------------------------------------------
1 | export * from './truncate.directive';
2 | export * from './truncate.module';
3 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/truncate/truncate.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { TruncateDirective } from './truncate.directive';
3 |
4 | @NgModule({
5 | declarations: [ TruncateDirective ],
6 | exports: [ TruncateDirective ]
7 | })
8 | export class TruncateModule {}
9 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/lib/ui.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { CommonModule } from '@angular/common';
3 |
4 | @NgModule({
5 | imports: [ CommonModule ],
6 | })
7 | export class UiModule {}
8 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/src/test-setup.ts:
--------------------------------------------------------------------------------
1 | import 'jest-preset-angular/setup-jest';
2 |
3 | class ResizeObserver {
4 | // eslint-disable-next-line @typescript-eslint/no-empty-function
5 | observe() {}
6 | // eslint-disable-next-line @typescript-eslint/no-empty-function
7 | unobserve() {}
8 | // eslint-disable-next-line @typescript-eslint/no-empty-function
9 | disconnect() {}
10 | }
11 |
12 | window.ResizeObserver = ResizeObserver;
13 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/styles/_details-page.scss:
--------------------------------------------------------------------------------
1 | @use './_mixins' as mixins;
2 | @use './_variables' as variables;
3 |
4 | details-header {
5 | @include mixins.flex-column($justify: unset, $align: baseline);
6 |
7 | background: white;
8 | border-bottom: variables.$border;
9 | padding: variables.$space-sm variables.$space-lg 0 variables.$space-lg;
10 |
11 | nav {
12 | min-width: calc(100vw - 64px);
13 | border-bottom: unset !important;
14 |
15 | .mat-drawer-opened ~ mat-sidenav-content & {
16 | min-width: calc(100vw - 264px);
17 | }
18 |
19 | .mat-tab-link {
20 | min-width: 100px;
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/styles/_fields.scss:
--------------------------------------------------------------------------------
1 | @use 'variables' as variables;
2 | @import 'mixins';
3 |
4 | $field-max-width: 700px;
5 | $field-max-width: 700px;
6 | $field-group-width: 500px;
7 | $field-group-width-medium: 450px;
8 | $field-group-width-narrow: 400px;
9 | $field-group-width-narrower: 350px;
10 | $field-margin-top: 0.85em;
11 | $field-margin-bottom: 20px;
12 | $field-color: variables.$gray-500;
13 | $field-shadow: rgba(variables.$black, 0.3);
14 | $field-label-width: 200px;
15 | $field-label-min-width: 120px;
16 |
17 |
18 |
19 | @mixin field($max-width: $field-max-width) {
20 | @include flex-row($justify: space-between);
21 | max-width: $max-width;
22 | color: variables.$dark-primary-text;
23 | }
24 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/styles/_icon-size.scss:
--------------------------------------------------------------------------------
1 | @use '@observability/ui/styles/mixins' as mixins;
2 |
3 | $size-shortcuts: ("icon-size": "icon-size");
4 |
5 | $range-start: 10;
6 | $range-end: 100;
7 |
8 | $range-values: ();
9 |
10 | @for $i from $range-start through $range-end {
11 | $range-values: append($range-values, $i);
12 | }
13 |
14 | @each $property, $shortcut in $size-shortcuts {
15 | @each $value in $range-values {
16 | // Do something with each value
17 | // For example, print the value
18 | mat-icon.#{$shortcut}-#{$value} {
19 | @include mixins.icon-size(#{$value}px !important);
20 | }
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/styles/_overlay.scss:
--------------------------------------------------------------------------------
1 | @use '@observability/ui/styles/variables' as variables;
2 |
3 | .base-overlay {
4 | overflow: hidden;
5 | border-radius: 4px;
6 | outline: 0;
7 | min-height: 64px;
8 | background: variables.$white;
9 | }
10 |
11 | .opaque-overlay {
12 | min-width: 112px;
13 | max-width: 280px;
14 | overflow: hidden;
15 | border-radius: 4px;
16 | outline: 0;
17 | min-height: 64px;
18 | background: variables.$white;
19 | }
20 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/styles/material/colors.scss:
--------------------------------------------------------------------------------
1 | @import '../variables';
2 |
3 | .mat-gray {
4 | circle {
5 | stroke: $gray-500;
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.base.json",
3 | "files": [],
4 | "include": [],
5 | "references": [
6 | {
7 | "path": "./tsconfig.lib.json"
8 | },
9 | {
10 | "path": "./tsconfig.spec.json"
11 | }
12 | ],
13 | "compilerOptions": {
14 | "forceConsistentCasingInFileNames": true,
15 | "strict": true,
16 | "noImplicitOverride": true,
17 | "noPropertyAccessFromIndexSignature": true,
18 | "noImplicitReturns": true,
19 | "noFallthroughCasesInSwitch": true,
20 | "target": "es2020"
21 | },
22 | "angularCompilerOptions": {
23 | "strictInjectionParameters": true,
24 | "strictInputAccessModifiers": true,
25 | "strictTemplates": true
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/tsconfig.lib.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../../dist/out-tsc",
5 | "declaration": true,
6 | "declarationMap": true,
7 | "inlineSources": true,
8 | "types": []
9 | },
10 | "exclude": [
11 | "src/test-setup.ts",
12 | "**/*.spec.ts",
13 | "**/*.test.ts",
14 | "jest.config.ts"
15 | ],
16 | "include": ["**/*.ts"]
17 | }
18 |
--------------------------------------------------------------------------------
/observability_ui/libs/ui/tsconfig.spec.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../../dist/out-tsc",
5 | "module": "commonjs",
6 | "types": ["jest", "node"],
7 | "strictPropertyInitialization": false,
8 | "target": "es2016"
9 | },
10 | "files": ["src/test-setup.ts"],
11 | "include": ["**/*.test.ts", "**/*.spec.ts", "**/*.d.ts", "jest.config.ts"]
12 | }
13 |
--------------------------------------------------------------------------------
/observability_ui/libs/webpack-config/mapped-paths.js:
--------------------------------------------------------------------------------
1 | module.exports.mappedPaths = [
2 | /* mapped paths to share */
3 | '@observability-ui/core',
4 | '@observability-ui/ui',
5 | '@observability-ui/translate',
6 | ];
7 |
--------------------------------------------------------------------------------
/observability_ui/libs/webpack-config/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "webpack-config",
3 | "version": "2.0.0",
4 | "description": "this is the shared configuration of observability mfe setup",
5 | "license": "MIT",
6 | "private": true
7 | }
8 |
--------------------------------------------------------------------------------
/observability_ui/tools/executors/version/executor.json:
--------------------------------------------------------------------------------
1 | {
2 | "executors": {
3 | "version": {
4 | "implementation": "./impl",
5 | "schema": "./schema.json",
6 | "description": "Updates apps version in ngsw-config.json file."
7 | }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/observability_ui/tools/executors/version/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "executors": "./executor.json"
3 | }
4 |
--------------------------------------------------------------------------------
/observability_ui/tools/executors/version/schema.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://json-schema.org/schema",
3 | "type": "object",
4 | "cli": "nx",
5 | "properties": {}
6 | }
7 |
--------------------------------------------------------------------------------
/observability_ui/tools/tsconfig.tools.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.base.json",
3 | "compilerOptions": {
4 | "outDir": "../dist/out-tsc/tools",
5 | "rootDir": ".",
6 | "module": "commonjs",
7 | "target": "es5",
8 | "types": ["node"],
9 | "importHelpers": false
10 | },
11 | "include": ["**/*.ts"]
12 | }
13 |
--------------------------------------------------------------------------------
/rules_engine/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/rules_engine/__init__.py
--------------------------------------------------------------------------------
/rules_engine/tests/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/rules_engine/tests/__init__.py
--------------------------------------------------------------------------------
/rules_engine/tests/integration/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/rules_engine/tests/integration/__init__.py
--------------------------------------------------------------------------------
/rules_engine/tests/unit/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/rules_engine/tests/unit/__init__.py
--------------------------------------------------------------------------------
/rules_engine/tests/unit/actions/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/rules_engine/tests/unit/actions/__init__.py
--------------------------------------------------------------------------------
/rules_engine/tests/unit/conftest.py:
--------------------------------------------------------------------------------
1 | from testlib.fixtures.entities import *
2 | from testlib.fixtures.v2_events import *
3 |
--------------------------------------------------------------------------------
/run_manager/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/run_manager/__init__.py
--------------------------------------------------------------------------------
/run_manager/event_handlers/__init__.py:
--------------------------------------------------------------------------------
1 | from .dataset_handler import *
2 | from .incomplete_instance_handler import *
3 | from .instance_handler import *
4 | from .run_handler import *
5 | from .schedule_handlers import *
6 | from .task_handler import *
7 | from .test_outcome_handler import *
8 |
--------------------------------------------------------------------------------
/run_manager/tests/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/run_manager/tests/__init__.py
--------------------------------------------------------------------------------
/run_manager/tests/integration/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/run_manager/tests/integration/__init__.py
--------------------------------------------------------------------------------
/run_manager/tests/integration/event_handlers/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/run_manager/tests/integration/event_handlers/__init__.py
--------------------------------------------------------------------------------
/run_manager/tests/unit/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/run_manager/tests/unit/__init__.py
--------------------------------------------------------------------------------
/scheduler/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/scheduler/__init__.py
--------------------------------------------------------------------------------
/scheduler/tests/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/scheduler/tests/__init__.py
--------------------------------------------------------------------------------
/scheduler/tests/integration/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/scheduler/tests/integration/__init__.py
--------------------------------------------------------------------------------
/scheduler/tests/unit/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/scheduler/tests/unit/__init__.py
--------------------------------------------------------------------------------
/scripts/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/scripts/__init__.py
--------------------------------------------------------------------------------
/scripts/invocations/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/scripts/invocations/__init__.py
--------------------------------------------------------------------------------
/setup.cfg:
--------------------------------------------------------------------------------
1 | # This file is here to support editable installs (pip install -e .)
2 | # https://github.com/pypa/setuptools/issues/2816
3 |
--------------------------------------------------------------------------------
/subcommand/README.md:
--------------------------------------------------------------------------------
1 | ## Subcommand Module
2 | This module provides a basis for creating tools with subcommands. It isolates some dynamic class creation & metaclass
3 | fun into a module that makes creating command line tools simpler to build.
4 |
5 | Check out the ``cli`` tool for example usage.
6 |
--------------------------------------------------------------------------------
/subcommand/__init__.py:
--------------------------------------------------------------------------------
1 | from .subcmd import SubcommandBase
2 |
3 | __all__ = ("SubcommandBase",)
4 |
--------------------------------------------------------------------------------
/subcommand/tests/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/subcommand/tests/__init__.py
--------------------------------------------------------------------------------
/testlib/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/testlib/__init__.py
--------------------------------------------------------------------------------
/testlib/fixtures/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DataKitchen/dataops-observability/fedfa3dbb2ae8252d68b6d666f1ebf02e1c83269/testlib/fixtures/__init__.py
--------------------------------------------------------------------------------
/testlib/peewee.py:
--------------------------------------------------------------------------------
1 | import contextlib
2 | from unittest.mock import Mock, patch
3 |
4 |
5 | @contextlib.contextmanager
6 | def patch_select(target: str, **kwargs):
7 | with patch(target=f"{target}.select") as select_mock:
8 | select_mock.return_value = select_mock
9 | for attr in ("join", "left_outer_join", "switch", "order_by", "where"):
10 | getattr(select_mock, attr).return_value = select_mock
11 | result_mock = Mock(**kwargs)
12 | for attr in ("get", "get_by_id", "__iter__"):
13 | setattr(select_mock, attr, result_mock)
14 | yield result_mock
15 |
--------------------------------------------------------------------------------