tasker-engine 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE +22 -0
- data/README.md +443 -0
- data/Rakefile +10 -0
- data/app/controllers/tasker/analytics_controller.rb +179 -0
- data/app/controllers/tasker/application_controller.rb +45 -0
- data/app/controllers/tasker/graphql_controller.rb +193 -0
- data/app/controllers/tasker/handlers_controller.rb +217 -0
- data/app/controllers/tasker/health_controller.rb +229 -0
- data/app/controllers/tasker/metrics_controller.rb +111 -0
- data/app/controllers/tasker/page_sort.rb +97 -0
- data/app/controllers/tasker/task_diagrams_controller.rb +30 -0
- data/app/controllers/tasker/tasks_controller.rb +123 -0
- data/app/controllers/tasker/workflow_steps_controller.rb +69 -0
- data/app/graphql/examples/all_tasks.graphql +22 -0
- data/app/graphql/examples/pending_tasks.graphql +23 -0
- data/app/graphql/tasker/graph_ql_types/annotation_type.rb +14 -0
- data/app/graphql/tasker/graph_ql_types/base_argument.rb +9 -0
- data/app/graphql/tasker/graph_ql_types/base_connection.rb +11 -0
- data/app/graphql/tasker/graph_ql_types/base_edge.rb +10 -0
- data/app/graphql/tasker/graph_ql_types/base_enum.rb +9 -0
- data/app/graphql/tasker/graph_ql_types/base_field.rb +10 -0
- data/app/graphql/tasker/graph_ql_types/base_input_object.rb +10 -0
- data/app/graphql/tasker/graph_ql_types/base_interface.rb +14 -0
- data/app/graphql/tasker/graph_ql_types/base_object.rb +10 -0
- data/app/graphql/tasker/graph_ql_types/base_scalar.rb +9 -0
- data/app/graphql/tasker/graph_ql_types/base_union.rb +11 -0
- data/app/graphql/tasker/graph_ql_types/dependent_system_object_map_type.rb +18 -0
- data/app/graphql/tasker/graph_ql_types/dependent_system_type.rb +13 -0
- data/app/graphql/tasker/graph_ql_types/mutation_type.rb +16 -0
- data/app/graphql/tasker/graph_ql_types/named_step_type.rb +16 -0
- data/app/graphql/tasker/graph_ql_types/named_task_type.rb +14 -0
- data/app/graphql/tasker/graph_ql_types/named_tasks_named_step_type.rb +19 -0
- data/app/graphql/tasker/graph_ql_types/node_type.rb +12 -0
- data/app/graphql/tasker/graph_ql_types/query_type.rb +20 -0
- data/app/graphql/tasker/graph_ql_types/task_annotation_type.rb +17 -0
- data/app/graphql/tasker/graph_ql_types/task_interface.rb +17 -0
- data/app/graphql/tasker/graph_ql_types/task_type.rb +26 -0
- data/app/graphql/tasker/graph_ql_types/workflow_step_type.rb +154 -0
- data/app/graphql/tasker/graph_ql_types.rb +42 -0
- data/app/graphql/tasker/mutations/base_mutation.rb +13 -0
- data/app/graphql/tasker/mutations/cancel_step.rb +29 -0
- data/app/graphql/tasker/mutations/cancel_task.rb +29 -0
- data/app/graphql/tasker/mutations/create_task.rb +52 -0
- data/app/graphql/tasker/mutations/update_step.rb +36 -0
- data/app/graphql/tasker/mutations/update_task.rb +41 -0
- data/app/graphql/tasker/queries/all_annotation_types.rb +17 -0
- data/app/graphql/tasker/queries/all_tasks.rb +23 -0
- data/app/graphql/tasker/queries/base_query.rb +9 -0
- data/app/graphql/tasker/queries/helpers.rb +16 -0
- data/app/graphql/tasker/queries/one_step.rb +24 -0
- data/app/graphql/tasker/queries/one_task.rb +18 -0
- data/app/graphql/tasker/queries/tasks_by_annotation.rb +31 -0
- data/app/graphql/tasker/queries/tasks_by_status.rb +30 -0
- data/app/graphql/tasker/tasker_rails_schema.rb +52 -0
- data/app/jobs/tasker/application_job.rb +8 -0
- data/app/jobs/tasker/metrics_export_job.rb +252 -0
- data/app/jobs/tasker/task_runner_job.rb +224 -0
- data/app/models/tasker/annotation_type.rb +26 -0
- data/app/models/tasker/application_record.rb +70 -0
- data/app/models/tasker/dependent_system.rb +26 -0
- data/app/models/tasker/dependent_system_object_map.rb +64 -0
- data/app/models/tasker/diagram/edge.rb +106 -0
- data/app/models/tasker/diagram/flowchart.rb +137 -0
- data/app/models/tasker/diagram/node.rb +99 -0
- data/app/models/tasker/named_step.rb +41 -0
- data/app/models/tasker/named_task.rb +121 -0
- data/app/models/tasker/named_tasks_named_step.rb +82 -0
- data/app/models/tasker/step_dag_relationship.rb +65 -0
- data/app/models/tasker/step_readiness_status.rb +59 -0
- data/app/models/tasker/task.rb +424 -0
- data/app/models/tasker/task_annotation.rb +36 -0
- data/app/models/tasker/task_diagram.rb +332 -0
- data/app/models/tasker/task_execution_context.rb +29 -0
- data/app/models/tasker/task_namespace.rb +41 -0
- data/app/models/tasker/task_transition.rb +235 -0
- data/app/models/tasker/workflow_step.rb +461 -0
- data/app/models/tasker/workflow_step_edge.rb +94 -0
- data/app/models/tasker/workflow_step_transition.rb +434 -0
- data/app/serializers/tasker/annotation_type_serializer.rb +8 -0
- data/app/serializers/tasker/handler_serializer.rb +109 -0
- data/app/serializers/tasker/task_annotation_serializer.rb +32 -0
- data/app/serializers/tasker/task_serializer.rb +168 -0
- data/app/serializers/tasker/workflow_step_serializer.rb +27 -0
- data/app/services/tasker/analytics_service.rb +409 -0
- data/app/views/tasker/task/_diagram.html.erb +32 -0
- data/config/initializers/dry_struct.rb +11 -0
- data/config/initializers/statesman.rb +6 -0
- data/config/initializers/tasker_orchestration.rb +17 -0
- data/config/initializers/time_formats.rb +4 -0
- data/config/routes.rb +34 -0
- data/config/tasker/subscriptions/example_integrations.yml +67 -0
- data/config/tasker/system_events.yml +305 -0
- data/db/functions/calculate_dependency_levels_v01.sql +45 -0
- data/db/functions/get_analytics_metrics_v01.sql +137 -0
- data/db/functions/get_slowest_steps_v01.sql +82 -0
- data/db/functions/get_slowest_tasks_v01.sql +96 -0
- data/db/functions/get_step_readiness_status_batch_v01.sql +140 -0
- data/db/functions/get_step_readiness_status_v01.sql +139 -0
- data/db/functions/get_system_health_counts_v01.sql +108 -0
- data/db/functions/get_task_execution_context_v01.sql +108 -0
- data/db/functions/get_task_execution_contexts_batch_v01.sql +104 -0
- data/db/init/schema.sql +2277 -0
- data/db/migrate/20250701165431_initial_tasker_schema.rb +116 -0
- data/db/views/tasker_step_dag_relationships_v01.sql +69 -0
- data/docs/APPLICATION_GENERATOR.md +384 -0
- data/docs/AUTH.md +1780 -0
- data/docs/CIRCUIT_BREAKER.md +224 -0
- data/docs/DEVELOPER_GUIDE.md +2665 -0
- data/docs/EVENT_SYSTEM.md +637 -0
- data/docs/EXECUTION_CONFIGURATION.md +341 -0
- data/docs/FLOW_CHART.md +149 -0
- data/docs/HEALTH.md +542 -0
- data/docs/METRICS.md +731 -0
- data/docs/OPTIMIZATION_PLAN.md +1479 -0
- data/docs/OVERVIEW.md +552 -0
- data/docs/QUICK_START.md +270 -0
- data/docs/REGISTRY_SYSTEMS.md +373 -0
- data/docs/REST_API.md +632 -0
- data/docs/ROADMAP.md +221 -0
- data/docs/SQL_FUNCTIONS.md +1408 -0
- data/docs/TASK_DIAGRAM.md +252 -0
- data/docs/TASK_EXECUTION_CONTROL_FLOW.md +237 -0
- data/docs/TELEMETRY.md +795 -0
- data/docs/TROUBLESHOOTING.md +756 -0
- data/docs/TaskHandlerGenerator.html +255 -0
- data/docs/Tasker/Analysis/RuntimeGraphAnalyzer.html +907 -0
- data/docs/Tasker/Analysis/TemplateGraphAnalyzer.html +1236 -0
- data/docs/Tasker/Analysis.html +117 -0
- data/docs/Tasker/AnalyticsController.html +450 -0
- data/docs/Tasker/AnalyticsService/BottleneckAnalytics.html +816 -0
- data/docs/Tasker/AnalyticsService/PerformanceAnalytics.html +586 -0
- data/docs/Tasker/AnalyticsService.html +2221 -0
- data/docs/Tasker/AnnotationType.html +137 -0
- data/docs/Tasker/AnnotationTypeSerializer.html +124 -0
- data/docs/Tasker/ApplicationController.html +147 -0
- data/docs/Tasker/ApplicationJob.html +128 -0
- data/docs/Tasker/ApplicationRecord.html +378 -0
- data/docs/Tasker/Authentication/AuthenticationError.html +124 -0
- data/docs/Tasker/Authentication/ConfigurationError.html +124 -0
- data/docs/Tasker/Authentication/Coordinator.html +242 -0
- data/docs/Tasker/Authentication/Interface.html +560 -0
- data/docs/Tasker/Authentication/InterfaceError.html +124 -0
- data/docs/Tasker/Authentication/NoneAuthenticator.html +338 -0
- data/docs/Tasker/Authentication.html +119 -0
- data/docs/Tasker/Authorization/AuthorizationError.html +139 -0
- data/docs/Tasker/Authorization/BaseCoordinator.html +927 -0
- data/docs/Tasker/Authorization/ConfigurationError.html +153 -0
- data/docs/Tasker/Authorization/ResourceConstants/ACTIONS.html +428 -0
- data/docs/Tasker/Authorization/ResourceConstants/RESOURCES.html +365 -0
- data/docs/Tasker/Authorization/ResourceConstants.html +146 -0
- data/docs/Tasker/Authorization/ResourceRegistry.html +882 -0
- data/docs/Tasker/Authorization/UnauthorizedError.html +153 -0
- data/docs/Tasker/Authorization.html +582 -0
- data/docs/Tasker/CacheCapabilities.html +167 -0
- data/docs/Tasker/CacheStrategy.html +1297 -0
- data/docs/Tasker/Concerns/Authenticatable.html +116 -0
- data/docs/Tasker/Concerns/Authorizable/AdminStatusChecker.html +256 -0
- data/docs/Tasker/Concerns/Authorizable.html +816 -0
- data/docs/Tasker/Concerns/ControllerAuthorizable.html +157 -0
- data/docs/Tasker/Concerns/EventPublisher.html +4023 -0
- data/docs/Tasker/Concerns/IdempotentStateTransitions.html +806 -0
- data/docs/Tasker/Concerns/LifecycleEventHelpers.html +129 -0
- data/docs/Tasker/Concerns/OrchestrationPublisher.html +129 -0
- data/docs/Tasker/Concerns/StateMachineBase/ClassMethods.html +1075 -0
- data/docs/Tasker/Concerns/StateMachineBase/StateMachineBase/ClassMethods.html +191 -0
- data/docs/Tasker/Concerns/StateMachineBase/StateMachineBase.html +126 -0
- data/docs/Tasker/Concerns/StateMachineBase.html +153 -0
- data/docs/Tasker/Concerns/StructuredLogging.html +1413 -0
- data/docs/Tasker/Concerns.html +117 -0
- data/docs/Tasker/Configuration/AuthConfiguration.html +1023 -0
- data/docs/Tasker/Configuration/ConfigurationProxy.html +581 -0
- data/docs/Tasker/Configuration/DatabaseConfiguration.html +475 -0
- data/docs/Tasker/Configuration/EngineConfiguration.html +1265 -0
- data/docs/Tasker/Configuration/HealthConfiguration.html +791 -0
- data/docs/Tasker/Configuration/TelemetryConfiguration.html +1308 -0
- data/docs/Tasker/Configuration/TelemetryConfigurationProxy.html +388 -0
- data/docs/Tasker/Configuration.html +1669 -0
- data/docs/Tasker/ConfigurationError.html +143 -0
- data/docs/Tasker/ConfiguredTask.html +514 -0
- data/docs/Tasker/Constants/EventDefinitions.html +590 -0
- data/docs/Tasker/Constants/LifecycleEvents.html +137 -0
- data/docs/Tasker/Constants/ObservabilityEvents/Step.html +152 -0
- data/docs/Tasker/Constants/ObservabilityEvents/Task.html +142 -0
- data/docs/Tasker/Constants/ObservabilityEvents.html +126 -0
- data/docs/Tasker/Constants/RegistryEvents.html +285 -0
- data/docs/Tasker/Constants/StepEvents.html +177 -0
- data/docs/Tasker/Constants/TaskEvents.html +167 -0
- data/docs/Tasker/Constants/TaskExecution/ExecutionStatus.html +207 -0
- data/docs/Tasker/Constants/TaskExecution/HealthStatus.html +191 -0
- data/docs/Tasker/Constants/TaskExecution/RecommendedAction.html +207 -0
- data/docs/Tasker/Constants/TaskExecution.html +126 -0
- data/docs/Tasker/Constants/TaskFinalization/ErrorMessages.html +132 -0
- data/docs/Tasker/Constants/TaskFinalization/PendingReasons.html +207 -0
- data/docs/Tasker/Constants/TaskFinalization/ReenqueueReasons.html +239 -0
- data/docs/Tasker/Constants/TaskFinalization.html +126 -0
- data/docs/Tasker/Constants/TaskStatuses.html +223 -0
- data/docs/Tasker/Constants/TestEvents.html +163 -0
- data/docs/Tasker/Constants/WorkflowEvents.html +222 -0
- data/docs/Tasker/Constants/WorkflowStepStatuses.html +223 -0
- data/docs/Tasker/Constants.html +561 -0
- data/docs/Tasker/DependentSystem.html +137 -0
- data/docs/Tasker/DependentSystemObjectMap.html +250 -0
- data/docs/Tasker/DetectorRegistry.html +598 -0
- data/docs/Tasker/Diagram/Edge.html +1191 -0
- data/docs/Tasker/Diagram/Flowchart.html +1539 -0
- data/docs/Tasker/Diagram/Node.html +1165 -0
- data/docs/Tasker/Diagram.html +117 -0
- data/docs/Tasker/Engine.html +215 -0
- data/docs/Tasker/Error.html +139 -0
- data/docs/Tasker/Events/Bus.html +1226 -0
- data/docs/Tasker/Events/Catalog/CatalogPrinter.html +258 -0
- data/docs/Tasker/Events/Catalog/CustomEventRegistrar.html +276 -0
- data/docs/Tasker/Events/Catalog/ExamplePayloadGenerator.html +294 -0
- data/docs/Tasker/Events/Catalog.html +1291 -0
- data/docs/Tasker/Events/CustomRegistry.html +943 -0
- data/docs/Tasker/Events/DefinitionLoader.html +575 -0
- data/docs/Tasker/Events/EventPayloadBuilder/ErrorInfoExtractor.html +286 -0
- data/docs/Tasker/Events/EventPayloadBuilder/StepPayloadBuilder.html +312 -0
- data/docs/Tasker/Events/EventPayloadBuilder.html +664 -0
- data/docs/Tasker/Events/Publisher.html +365 -0
- data/docs/Tasker/Events/Subscribers/BaseSubscriber/ErrorCategorizer/ErrorTypeClassifier.html +1128 -0
- data/docs/Tasker/Events/Subscribers/BaseSubscriber/ErrorCategorizer.html +270 -0
- data/docs/Tasker/Events/Subscribers/BaseSubscriber/MetricTagsExtractor.html +266 -0
- data/docs/Tasker/Events/Subscribers/BaseSubscriber.html +2556 -0
- data/docs/Tasker/Events/Subscribers/MetricsSubscriber.html +723 -0
- data/docs/Tasker/Events/Subscribers/TelemetrySubscriber.html +2251 -0
- data/docs/Tasker/Events/Subscribers.html +117 -0
- data/docs/Tasker/Events/SubscriptionLoader.html +493 -0
- data/docs/Tasker/Events.html +294 -0
- data/docs/Tasker/EventsGenerator.html +459 -0
- data/docs/Tasker/Functions/FunctionBasedAnalyticsMetrics/AnalyticsMetrics.html +135 -0
- data/docs/Tasker/Functions/FunctionBasedAnalyticsMetrics.html +412 -0
- data/docs/Tasker/Functions/FunctionBasedDependencyLevels.html +598 -0
- data/docs/Tasker/Functions/FunctionBasedSlowestSteps/SlowestStep.html +135 -0
- data/docs/Tasker/Functions/FunctionBasedSlowestSteps.html +453 -0
- data/docs/Tasker/Functions/FunctionBasedSlowestTasks/SlowestTask.html +135 -0
- data/docs/Tasker/Functions/FunctionBasedSlowestTasks.html +453 -0
- data/docs/Tasker/Functions/FunctionBasedStepReadinessStatus.html +1457 -0
- data/docs/Tasker/Functions/FunctionBasedSystemHealthCounts/HealthMetrics.html +135 -0
- data/docs/Tasker/Functions/FunctionBasedSystemHealthCounts.html +370 -0
- data/docs/Tasker/Functions/FunctionBasedTaskExecutionContext.html +1250 -0
- data/docs/Tasker/Functions/FunctionWrapper.html +479 -0
- data/docs/Tasker/Functions.html +117 -0
- data/docs/Tasker/Generators/AuthenticatorGenerator/UsageInstructionsFormatter.html +244 -0
- data/docs/Tasker/Generators/AuthenticatorGenerator.html +373 -0
- data/docs/Tasker/Generators/AuthorizationCoordinatorGenerator.html +430 -0
- data/docs/Tasker/Generators/SubscriberGenerator.html +377 -0
- data/docs/Tasker/Generators/TaskHandlerGenerator.html +263 -0
- data/docs/Tasker/Generators.html +117 -0
- data/docs/Tasker/GraphQLTypes/AnnotationType.html +132 -0
- data/docs/Tasker/GraphQLTypes/BaseArgument.html +124 -0
- data/docs/Tasker/GraphQLTypes/BaseConnection.html +124 -0
- data/docs/Tasker/GraphQLTypes/BaseEdge.html +130 -0
- data/docs/Tasker/GraphQLTypes/BaseEnum.html +124 -0
- data/docs/Tasker/GraphQLTypes/BaseField.html +124 -0
- data/docs/Tasker/GraphQLTypes/BaseInputObject.html +124 -0
- data/docs/Tasker/GraphQLTypes/BaseInterface.html +116 -0
- data/docs/Tasker/GraphQLTypes/BaseObject.html +128 -0
- data/docs/Tasker/GraphQLTypes/BaseScalar.html +124 -0
- data/docs/Tasker/GraphQLTypes/BaseUnion.html +124 -0
- data/docs/Tasker/GraphQLTypes/DependentSystemObjectMapType.html +132 -0
- data/docs/Tasker/GraphQLTypes/DependentSystemType.html +132 -0
- data/docs/Tasker/GraphQLTypes/MutationType.html +132 -0
- data/docs/Tasker/GraphQLTypes/NamedStepType.html +132 -0
- data/docs/Tasker/GraphQLTypes/NamedTaskType.html +132 -0
- data/docs/Tasker/GraphQLTypes/NamedTasksNamedStepType.html +132 -0
- data/docs/Tasker/GraphQLTypes/NodeType.html +118 -0
- data/docs/Tasker/GraphQLTypes/QueryType.html +139 -0
- data/docs/Tasker/GraphQLTypes/TaskAnnotationType.html +132 -0
- data/docs/Tasker/GraphQLTypes/TaskInterface.html +111 -0
- data/docs/Tasker/GraphQLTypes/TaskType.html +201 -0
- data/docs/Tasker/GraphQLTypes/WorkflowStepType.html +694 -0
- data/docs/Tasker/GraphQLTypes.html +130 -0
- data/docs/Tasker/GraphqlController.html +251 -0
- data/docs/Tasker/HandlerFactory.html +1518 -0
- data/docs/Tasker/HandlerSerializer.html +682 -0
- data/docs/Tasker/HandlersController.html +574 -0
- data/docs/Tasker/HashIdentityStrategy.html +278 -0
- data/docs/Tasker/Health/ReadinessChecker.html +712 -0
- data/docs/Tasker/Health/StatusChecker.html +653 -0
- data/docs/Tasker/Health.html +117 -0
- data/docs/Tasker/HealthController.html +523 -0
- data/docs/Tasker/IdentityStrategy.html +276 -0
- data/docs/Tasker/InvalidTaskHandlerConfig.html +135 -0
- data/docs/Tasker/LifecycleEvents/Events/Step.html +162 -0
- data/docs/Tasker/LifecycleEvents/Events/Task.html +162 -0
- data/docs/Tasker/LifecycleEvents/Events.html +204 -0
- data/docs/Tasker/LifecycleEvents/Publisher.html +132 -0
- data/docs/Tasker/LifecycleEvents.html +799 -0
- data/docs/Tasker/Logging/CorrelationIdGenerator.html +688 -0
- data/docs/Tasker/Logging.html +115 -0
- data/docs/Tasker/MetricsController.html +293 -0
- data/docs/Tasker/MetricsExportJob.html +414 -0
- data/docs/Tasker/Mutations/BaseMutation.html +128 -0
- data/docs/Tasker/Mutations/CancelStep.html +219 -0
- data/docs/Tasker/Mutations/CancelTask.html +221 -0
- data/docs/Tasker/Mutations/CreateTask.html +243 -0
- data/docs/Tasker/Mutations/UpdateStep.html +243 -0
- data/docs/Tasker/Mutations/UpdateTask.html +243 -0
- data/docs/Tasker/Mutations.html +117 -0
- data/docs/Tasker/NamedStep.html +216 -0
- data/docs/Tasker/NamedTask.html +910 -0
- data/docs/Tasker/NamedTasksNamedStep.html +435 -0
- data/docs/Tasker/Orchestration/BackoffCalculator.html +404 -0
- data/docs/Tasker/Orchestration/ConnectionBuilder/ConfigValidator.html +258 -0
- data/docs/Tasker/Orchestration/ConnectionBuilder.html +435 -0
- data/docs/Tasker/Orchestration/ConnectionPoolIntelligence.html +513 -0
- data/docs/Tasker/Orchestration/Coordinator.html +641 -0
- data/docs/Tasker/Orchestration/FutureStateAnalyzer.html +1045 -0
- data/docs/Tasker/Orchestration/Orchestrator.html +679 -0
- data/docs/Tasker/Orchestration/PluginIntegration.html +1127 -0
- data/docs/Tasker/Orchestration/ResponseProcessor.html +504 -0
- data/docs/Tasker/Orchestration/RetryHeaderParser.html +304 -0
- data/docs/Tasker/Orchestration/StepExecutor.html +995 -0
- data/docs/Tasker/Orchestration/StepSequenceFactory.html +644 -0
- data/docs/Tasker/Orchestration/TaskFinalizer/BlockageChecker.html +264 -0
- data/docs/Tasker/Orchestration/TaskFinalizer/ContextManager.html +254 -0
- data/docs/Tasker/Orchestration/TaskFinalizer/DelayCalculator.html +556 -0
- data/docs/Tasker/Orchestration/TaskFinalizer/FinalizationDecisionMaker.html +348 -0
- data/docs/Tasker/Orchestration/TaskFinalizer/FinalizationProcessor.html +286 -0
- data/docs/Tasker/Orchestration/TaskFinalizer/ReasonDeterminer.html +432 -0
- data/docs/Tasker/Orchestration/TaskFinalizer/ReenqueueManager.html +296 -0
- data/docs/Tasker/Orchestration/TaskFinalizer/UnclearStateHandler.html +314 -0
- data/docs/Tasker/Orchestration/TaskFinalizer.html +1212 -0
- data/docs/Tasker/Orchestration/TaskInitializer.html +766 -0
- data/docs/Tasker/Orchestration/TaskReenqueuer.html +506 -0
- data/docs/Tasker/Orchestration/ViableStepDiscovery.html +442 -0
- data/docs/Tasker/Orchestration/WorkflowCoordinator.html +510 -0
- data/docs/Tasker/Orchestration.html +130 -0
- data/docs/Tasker/PageSort/PageSortParamsBuilder.html +296 -0
- data/docs/Tasker/PageSort.html +247 -0
- data/docs/Tasker/PermanentError.html +518 -0
- data/docs/Tasker/ProceduralError.html +147 -0
- data/docs/Tasker/Queries/AllAnnotationTypes.html +217 -0
- data/docs/Tasker/Queries/AllTasks.html +221 -0
- data/docs/Tasker/Queries/BaseQuery.html +128 -0
- data/docs/Tasker/Queries/Helpers.html +187 -0
- data/docs/Tasker/Queries/OneStep.html +225 -0
- data/docs/Tasker/Queries/OneTask.html +217 -0
- data/docs/Tasker/Queries/TasksByAnnotation.html +231 -0
- data/docs/Tasker/Queries/TasksByStatus.html +233 -0
- data/docs/Tasker/Queries.html +119 -0
- data/docs/Tasker/Railtie.html +124 -0
- data/docs/Tasker/Registry/BaseRegistry.html +1690 -0
- data/docs/Tasker/Registry/EventPublisher.html +667 -0
- data/docs/Tasker/Registry/InterfaceValidator.html +569 -0
- data/docs/Tasker/Registry/RegistrationError.html +132 -0
- data/docs/Tasker/Registry/RegistryError.html +139 -0
- data/docs/Tasker/Registry/StatisticsCollector.html +841 -0
- data/docs/Tasker/Registry/SubscriberRegistry.html +1504 -0
- data/docs/Tasker/Registry/ValidationError.html +132 -0
- data/docs/Tasker/Registry.html +119 -0
- data/docs/Tasker/RetryableError.html +515 -0
- data/docs/Tasker/StateMachine/Compatibility.html +282 -0
- data/docs/Tasker/StateMachine/InvalidStateTransition.html +135 -0
- data/docs/Tasker/StateMachine/StepStateMachine/StandardizedPayloadBuilder.html +260 -0
- data/docs/Tasker/StateMachine/StepStateMachine.html +2215 -0
- data/docs/Tasker/StateMachine/TaskStateMachine.html +734 -0
- data/docs/Tasker/StateMachine.html +602 -0
- data/docs/Tasker/StepDagRelationship.html +657 -0
- data/docs/Tasker/StepHandler/Api/Config.html +1091 -0
- data/docs/Tasker/StepHandler/Api.html +884 -0
- data/docs/Tasker/StepHandler/AutomaticEventPublishing.html +321 -0
- data/docs/Tasker/StepHandler/Base.html +970 -0
- data/docs/Tasker/StepHandler.html +119 -0
- data/docs/Tasker/StepReadinessStatus.html +836 -0
- data/docs/Tasker/Task.html +2575 -0
- data/docs/Tasker/TaskAnnotation.html +137 -0
- data/docs/Tasker/TaskAnnotationSerializer.html +124 -0
- data/docs/Tasker/TaskBuilder/StepNameValidator.html +264 -0
- data/docs/Tasker/TaskBuilder/StepTemplateDefiner.html +264 -0
- data/docs/Tasker/TaskBuilder.html +764 -0
- data/docs/Tasker/TaskDiagram/StepToStepEdgeBuilder.html +260 -0
- data/docs/Tasker/TaskDiagram/TaskToRootStepEdgeBuilder.html +290 -0
- data/docs/Tasker/TaskDiagram.html +548 -0
- data/docs/Tasker/TaskDiagramsController.html +240 -0
- data/docs/Tasker/TaskExecutionContext.html +469 -0
- data/docs/Tasker/TaskHandler/ClassMethods/StepTemplateDefiner/ClassBasedEventRegistrar.html +238 -0
- data/docs/Tasker/TaskHandler/ClassMethods/StepTemplateDefiner/YamlEventRegistrar.html +254 -0
- data/docs/Tasker/TaskHandler/ClassMethods/StepTemplateDefiner.html +988 -0
- data/docs/Tasker/TaskHandler/ClassMethods.html +357 -0
- data/docs/Tasker/TaskHandler/InstanceMethods.html +1396 -0
- data/docs/Tasker/TaskHandler/StepGroup.html +1748 -0
- data/docs/Tasker/TaskHandler.html +271 -0
- data/docs/Tasker/TaskNamespace.html +312 -0
- data/docs/Tasker/TaskRunnerJob.html +406 -0
- data/docs/Tasker/TaskSerializer.html +474 -0
- data/docs/Tasker/TaskTransition.html +1517 -0
- data/docs/Tasker/TaskWorkflowSummary.html +988 -0
- data/docs/Tasker/TaskerRailsSchema/InvalidObjectTypeError.html +132 -0
- data/docs/Tasker/TaskerRailsSchema/TypeResolutionError.html +139 -0
- data/docs/Tasker/TaskerRailsSchema/UnknownInterfaceError.html +132 -0
- data/docs/Tasker/TaskerRailsSchema.html +384 -0
- data/docs/Tasker/TasksController.html +595 -0
- data/docs/Tasker/Telemetry/EventMapping.html +1307 -0
- data/docs/Tasker/Telemetry/EventRouter.html +2178 -0
- data/docs/Tasker/Telemetry/Events/ExportEvents.html +246 -0
- data/docs/Tasker/Telemetry/Events.html +115 -0
- data/docs/Tasker/Telemetry/ExportCoordinator/DistributedLockTimeoutError.html +135 -0
- data/docs/Tasker/Telemetry/ExportCoordinator.html +2137 -0
- data/docs/Tasker/Telemetry/IntelligentCacheManager.html +1083 -0
- data/docs/Tasker/Telemetry/LogBackend.html +1088 -0
- data/docs/Tasker/Telemetry/MetricTypes/Counter.html +1054 -0
- data/docs/Tasker/Telemetry/MetricTypes/Gauge.html +1270 -0
- data/docs/Tasker/Telemetry/MetricTypes/Histogram.html +1492 -0
- data/docs/Tasker/Telemetry/MetricTypes.html +153 -0
- data/docs/Tasker/Telemetry/MetricsBackend.html +2510 -0
- data/docs/Tasker/Telemetry/MetricsExportService.html +578 -0
- data/docs/Tasker/Telemetry/PluginRegistry.html +1774 -0
- data/docs/Tasker/Telemetry/Plugins/BaseExporter.html +1835 -0
- data/docs/Tasker/Telemetry/Plugins/CsvExporter.html +768 -0
- data/docs/Tasker/Telemetry/Plugins/JsonExporter.html +747 -0
- data/docs/Tasker/Telemetry/Plugins.html +117 -0
- data/docs/Tasker/Telemetry/PrometheusExporter.html +481 -0
- data/docs/Tasker/Telemetry/TraceBackend.html +891 -0
- data/docs/Tasker/Telemetry.html +130 -0
- data/docs/Tasker/Types/AuthConfig.html +886 -0
- data/docs/Tasker/Types/BackoffConfig.html +1063 -0
- data/docs/Tasker/Types/BaseConfig.html +227 -0
- data/docs/Tasker/Types/CacheConfig.html +1731 -0
- data/docs/Tasker/Types/DatabaseConfig.html +388 -0
- data/docs/Tasker/Types/DependencyGraph.html +526 -0
- data/docs/Tasker/Types/DependencyGraphConfig.html +753 -0
- data/docs/Tasker/Types/EngineConfig.html +1181 -0
- data/docs/Tasker/Types/ExecutionConfig.html +1963 -0
- data/docs/Tasker/Types/GraphEdge.html +517 -0
- data/docs/Tasker/Types/GraphMetadata.html +781 -0
- data/docs/Tasker/Types/GraphNode.html +694 -0
- data/docs/Tasker/Types/HealthConfig.html +784 -0
- data/docs/Tasker/Types/StepSequence.html +353 -0
- data/docs/Tasker/Types/StepTemplate.html +1193 -0
- data/docs/Tasker/Types/TaskRequest.html +1179 -0
- data/docs/Tasker/Types/TelemetryConfig.html +2746 -0
- data/docs/Tasker/Types.html +154 -0
- data/docs/Tasker/WorkflowStep/StepFinder.html +282 -0
- data/docs/Tasker/WorkflowStep.html +2724 -0
- data/docs/Tasker/WorkflowStepEdge.html +304 -0
- data/docs/Tasker/WorkflowStepSerializer.html +305 -0
- data/docs/Tasker/WorkflowStepTransition/TransitionDescriptionFormatter.html +282 -0
- data/docs/Tasker/WorkflowStepTransition.html +2201 -0
- data/docs/Tasker/WorkflowStepsController.html +462 -0
- data/docs/Tasker.html +452 -0
- data/docs/VISION.md +584 -0
- data/docs/WHY.md +21 -0
- data/docs/_index.html +2375 -0
- data/docs/class_list.html +54 -0
- data/docs/css/common.css +1 -0
- data/docs/css/full_list.css +58 -0
- data/docs/css/style.css +503 -0
- data/docs/events/migration_plan_outcomes.md +80 -0
- data/docs/file.README.html +541 -0
- data/docs/file_list.html +59 -0
- data/docs/frames.html +22 -0
- data/docs/index.html +541 -0
- data/docs/js/app.js +344 -0
- data/docs/js/full_list.js +242 -0
- data/docs/js/jquery.js +4 -0
- data/docs/method_list.html +9182 -0
- data/docs/top-level-namespace.html +110 -0
- data/lib/generators/tasker/authenticator_generator.rb +301 -0
- data/lib/generators/tasker/authorization_coordinator_generator.rb +139 -0
- data/lib/generators/tasker/events_generator.rb +91 -0
- data/lib/generators/tasker/subscriber_generator.rb +107 -0
- data/lib/generators/tasker/task_handler_generator.rb +138 -0
- data/lib/generators/tasker/templates/api_token_authenticator.rb.erb +113 -0
- data/lib/generators/tasker/templates/api_token_authenticator_spec.rb.erb +144 -0
- data/lib/generators/tasker/templates/authorization_coordinator.rb.erb +95 -0
- data/lib/generators/tasker/templates/authorization_coordinator_spec.rb.erb +142 -0
- data/lib/generators/tasker/templates/custom_authenticator.rb.erb +108 -0
- data/lib/generators/tasker/templates/custom_authenticator_spec.rb.erb +162 -0
- data/lib/generators/tasker/templates/custom_events.yml.erb +62 -0
- data/lib/generators/tasker/templates/custom_subscriber.rb.erb +72 -0
- data/lib/generators/tasker/templates/devise_authenticator.rb.erb +101 -0
- data/lib/generators/tasker/templates/devise_authenticator_spec.rb.erb +126 -0
- data/lib/generators/tasker/templates/initialize.rb.erb +202 -0
- data/lib/generators/tasker/templates/jwt_authenticator.rb.erb +144 -0
- data/lib/generators/tasker/templates/jwt_authenticator_spec.rb.erb +298 -0
- data/lib/generators/tasker/templates/metrics_subscriber.rb.erb +258 -0
- data/lib/generators/tasker/templates/metrics_subscriber_spec.rb.erb +308 -0
- data/lib/generators/tasker/templates/omniauth_authenticator.rb.erb +135 -0
- data/lib/generators/tasker/templates/omniauth_authenticator_spec.rb.erb +196 -0
- data/lib/generators/tasker/templates/opentelemetry_initializer.rb +52 -0
- data/lib/generators/tasker/templates/subscriber.rb.erb +64 -0
- data/lib/generators/tasker/templates/subscriber_spec.rb.erb +80 -0
- data/lib/generators/tasker/templates/task_config.yaml.erb +117 -0
- data/lib/generators/tasker/templates/task_handler.rb.erb +59 -0
- data/lib/generators/tasker/templates/task_handler_spec.rb.erb +159 -0
- data/lib/tasker/analysis/runtime_graph_analyzer.rb +1168 -0
- data/lib/tasker/analysis/template_graph_analyzer.rb +328 -0
- data/lib/tasker/authentication/coordinator.rb +78 -0
- data/lib/tasker/authentication/errors.rb +9 -0
- data/lib/tasker/authentication/interface.rb +36 -0
- data/lib/tasker/authentication/none_authenticator.rb +26 -0
- data/lib/tasker/authorization/base_coordinator.rb +112 -0
- data/lib/tasker/authorization/errors.rb +26 -0
- data/lib/tasker/authorization/resource_constants.rb +74 -0
- data/lib/tasker/authorization/resource_registry.rb +143 -0
- data/lib/tasker/authorization.rb +75 -0
- data/lib/tasker/cache_capabilities.rb +131 -0
- data/lib/tasker/cache_strategy.rb +469 -0
- data/lib/tasker/concerns/authenticatable.rb +41 -0
- data/lib/tasker/concerns/authorizable.rb +204 -0
- data/lib/tasker/concerns/controller_authorizable.rb +124 -0
- data/lib/tasker/concerns/event_publisher.rb +716 -0
- data/lib/tasker/concerns/idempotent_state_transitions.rb +128 -0
- data/lib/tasker/concerns/state_machine_base.rb +218 -0
- data/lib/tasker/concerns/structured_logging.rb +387 -0
- data/lib/tasker/configuration.rb +325 -0
- data/lib/tasker/constants/event_definitions.rb +147 -0
- data/lib/tasker/constants/registry_events.rb +54 -0
- data/lib/tasker/constants.rb +417 -0
- data/lib/tasker/engine.rb +90 -0
- data/lib/tasker/errors.rb +90 -0
- data/lib/tasker/events/catalog.rb +432 -0
- data/lib/tasker/events/custom_registry.rb +175 -0
- data/lib/tasker/events/definition_loader.rb +199 -0
- data/lib/tasker/events/event_payload_builder.rb +461 -0
- data/lib/tasker/events/publisher.rb +149 -0
- data/lib/tasker/events/subscribers/base_subscriber.rb +601 -0
- data/lib/tasker/events/subscribers/metrics_subscriber.rb +120 -0
- data/lib/tasker/events/subscribers/telemetry_subscriber.rb +462 -0
- data/lib/tasker/events/subscription_loader.rb +161 -0
- data/lib/tasker/events.rb +37 -0
- data/lib/tasker/functions/function_based_analytics_metrics.rb +103 -0
- data/lib/tasker/functions/function_based_dependency_levels.rb +54 -0
- data/lib/tasker/functions/function_based_slowest_steps.rb +84 -0
- data/lib/tasker/functions/function_based_slowest_tasks.rb +84 -0
- data/lib/tasker/functions/function_based_step_readiness_status.rb +183 -0
- data/lib/tasker/functions/function_based_system_health_counts.rb +94 -0
- data/lib/tasker/functions/function_based_task_execution_context.rb +148 -0
- data/lib/tasker/functions/function_wrapper.rb +42 -0
- data/lib/tasker/functions.rb +12 -0
- data/lib/tasker/handler_factory.rb +322 -0
- data/lib/tasker/health/readiness_checker.rb +186 -0
- data/lib/tasker/health/status_checker.rb +203 -0
- data/lib/tasker/identity_strategy.rb +38 -0
- data/lib/tasker/logging/correlation_id_generator.rb +120 -0
- data/lib/tasker/orchestration/backoff_calculator.rb +184 -0
- data/lib/tasker/orchestration/connection_builder.rb +122 -0
- data/lib/tasker/orchestration/connection_pool_intelligence.rb +177 -0
- data/lib/tasker/orchestration/coordinator.rb +119 -0
- data/lib/tasker/orchestration/future_state_analyzer.rb +137 -0
- data/lib/tasker/orchestration/plugin_integration.rb +124 -0
- data/lib/tasker/orchestration/response_processor.rb +168 -0
- data/lib/tasker/orchestration/retry_header_parser.rb +78 -0
- data/lib/tasker/orchestration/step_executor.rb +941 -0
- data/lib/tasker/orchestration/step_sequence_factory.rb +67 -0
- data/lib/tasker/orchestration/task_finalizer.rb +564 -0
- data/lib/tasker/orchestration/task_initializer.rb +140 -0
- data/lib/tasker/orchestration/task_reenqueuer.rb +71 -0
- data/lib/tasker/orchestration/viable_step_discovery.rb +65 -0
- data/lib/tasker/orchestration/workflow_coordinator.rb +294 -0
- data/lib/tasker/orchestration.rb +45 -0
- data/lib/tasker/railtie.rb +9 -0
- data/lib/tasker/registry/base_registry.rb +177 -0
- data/lib/tasker/registry/event_publisher.rb +91 -0
- data/lib/tasker/registry/interface_validator.rb +140 -0
- data/lib/tasker/registry/statistics_collector.rb +381 -0
- data/lib/tasker/registry/subscriber_registry.rb +285 -0
- data/lib/tasker/registry.rb +22 -0
- data/lib/tasker/state_machine/step_state_machine.rb +508 -0
- data/lib/tasker/state_machine/task_state_machine.rb +192 -0
- data/lib/tasker/state_machine.rb +83 -0
- data/lib/tasker/step_handler/api.rb +410 -0
- data/lib/tasker/step_handler/base.rb +206 -0
- data/lib/tasker/task_builder.rb +432 -0
- data/lib/tasker/task_handler/class_methods.rb +324 -0
- data/lib/tasker/task_handler/instance_methods.rb +293 -0
- data/lib/tasker/task_handler/step_group.rb +182 -0
- data/lib/tasker/task_handler.rb +43 -0
- data/lib/tasker/telemetry/event_mapping.rb +126 -0
- data/lib/tasker/telemetry/event_router.rb +318 -0
- data/lib/tasker/telemetry/events/export_events.rb +38 -0
- data/lib/tasker/telemetry/export_coordinator.rb +497 -0
- data/lib/tasker/telemetry/intelligent_cache_manager.rb +508 -0
- data/lib/tasker/telemetry/log_backend.rb +224 -0
- data/lib/tasker/telemetry/metric_types.rb +368 -0
- data/lib/tasker/telemetry/metrics_backend.rb +1227 -0
- data/lib/tasker/telemetry/metrics_export_service.rb +392 -0
- data/lib/tasker/telemetry/plugin_registry.rb +333 -0
- data/lib/tasker/telemetry/plugins/base_exporter.rb +246 -0
- data/lib/tasker/telemetry/plugins/csv_exporter.rb +198 -0
- data/lib/tasker/telemetry/plugins/json_exporter.rb +141 -0
- data/lib/tasker/telemetry/prometheus_exporter.rb +249 -0
- data/lib/tasker/telemetry/trace_backend.rb +186 -0
- data/lib/tasker/telemetry.rb +59 -0
- data/lib/tasker/types/auth_config.rb +81 -0
- data/lib/tasker/types/backoff_config.rb +142 -0
- data/lib/tasker/types/cache_config.rb +257 -0
- data/lib/tasker/types/database_config.rb +39 -0
- data/lib/tasker/types/dependency_graph.rb +225 -0
- data/lib/tasker/types/dependency_graph_config.rb +149 -0
- data/lib/tasker/types/engine_config.rb +131 -0
- data/lib/tasker/types/execution_config.rb +289 -0
- data/lib/tasker/types/health_config.rb +84 -0
- data/lib/tasker/types/step_sequence.rb +24 -0
- data/lib/tasker/types/step_template.rb +63 -0
- data/lib/tasker/types/task_request.rb +60 -0
- data/lib/tasker/types/telemetry_config.rb +273 -0
- data/lib/tasker/types.rb +64 -0
- data/lib/tasker/version.rb +7 -0
- data/lib/tasker.rb +82 -0
- data/lib/tasks/tasker_tasks.rake +302 -0
- metadata +958 -0
@@ -0,0 +1,198 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'csv'
|
4
|
+
require_relative 'base_exporter'
|
5
|
+
|
6
|
+
module Tasker
|
7
|
+
module Telemetry
|
8
|
+
module Plugins
|
9
|
+
# CSV format exporter for metrics data
|
10
|
+
#
|
11
|
+
# Exports metrics in CSV format with configurable columns and headers.
|
12
|
+
# Flattens metric labels into separate columns for tabular representation.
|
13
|
+
#
|
14
|
+
# @example Basic Usage
|
15
|
+
# exporter = Tasker::Telemetry::Plugins::CsvExporter.new
|
16
|
+
# result = exporter.export(metrics_data, include_headers: true)
|
17
|
+
#
|
18
|
+
# @example With Custom Columns
|
19
|
+
# exporter = Tasker::Telemetry::Plugins::CsvExporter.new(
|
20
|
+
# columns: %w[timestamp name type value status]
|
21
|
+
# )
|
22
|
+
class CsvExporter < BaseExporter
|
23
|
+
VERSION = '1.0.0'
|
24
|
+
DESCRIPTION = 'CSV format exporter with configurable columns and label flattening'
|
25
|
+
|
26
|
+
DEFAULT_COLUMNS = %w[
|
27
|
+
timestamp
|
28
|
+
name
|
29
|
+
type
|
30
|
+
value
|
31
|
+
labels
|
32
|
+
].freeze
|
33
|
+
|
34
|
+
# @param options [Hash] Configuration options
|
35
|
+
# @option options [Array<String>] :columns Column names to include
|
36
|
+
# @option options [String] :separator CSV field separator
|
37
|
+
# @option options [Boolean] :flatten_labels Flatten labels into separate columns
|
38
|
+
def initialize(options = {})
|
39
|
+
super()
|
40
|
+
@columns = options.fetch(:columns, DEFAULT_COLUMNS)
|
41
|
+
@separator = options.fetch(:separator, ',')
|
42
|
+
@flatten_labels = options.fetch(:flatten_labels, true)
|
43
|
+
end
|
44
|
+
|
45
|
+
# Export metrics data as CSV
|
46
|
+
#
|
47
|
+
# @param metrics_data [Hash] Metrics data from MetricsBackend
|
48
|
+
# @param options [Hash] Export options
|
49
|
+
# @option options [Boolean] :include_headers Include CSV headers
|
50
|
+
# @option options [String] :row_separator Row separator character
|
51
|
+
# @return [Hash] Export result with CSV string
|
52
|
+
def export(metrics_data, options = {})
|
53
|
+
include_headers = options.fetch(:include_headers, true)
|
54
|
+
row_separator = options.fetch(:row_separator, "\n")
|
55
|
+
|
56
|
+
metrics = metrics_data[:metrics] || {}
|
57
|
+
timestamp = metrics_data[:timestamp]
|
58
|
+
|
59
|
+
return empty_export if metrics.empty?
|
60
|
+
|
61
|
+
# Build CSV data
|
62
|
+
csv_data = build_csv_data(metrics, timestamp, include_headers, row_separator)
|
63
|
+
|
64
|
+
{
|
65
|
+
success: true,
|
66
|
+
format: 'csv',
|
67
|
+
data: csv_data,
|
68
|
+
size_bytes: csv_data.bytesize,
|
69
|
+
metrics_count: metrics.size,
|
70
|
+
rows: metrics.size + (include_headers ? 1 : 0)
|
71
|
+
}
|
72
|
+
end
|
73
|
+
|
74
|
+
# Check if format is supported
|
75
|
+
#
|
76
|
+
# @param format [String, Symbol] Format to check
|
77
|
+
# @return [Boolean] True if CSV format is supported
|
78
|
+
def supports_format?(format)
|
79
|
+
%w[csv].include?(format.to_s.downcase)
|
80
|
+
end
|
81
|
+
|
82
|
+
# Get supported formats
|
83
|
+
#
|
84
|
+
# @return [Array<String>] List of supported formats
|
85
|
+
def supported_formats
|
86
|
+
%w[csv]
|
87
|
+
end
|
88
|
+
|
89
|
+
private
|
90
|
+
|
91
|
+
# Build CSV data from metrics
|
92
|
+
def build_csv_data(metrics, timestamp, include_headers, row_separator)
|
93
|
+
# Determine all label keys if flattening
|
94
|
+
all_label_keys = if @flatten_labels
|
95
|
+
extract_all_label_keys(metrics)
|
96
|
+
else
|
97
|
+
[]
|
98
|
+
end
|
99
|
+
|
100
|
+
# Build headers
|
101
|
+
headers = build_headers(all_label_keys)
|
102
|
+
|
103
|
+
# Build rows
|
104
|
+
rows = []
|
105
|
+
rows << headers if include_headers
|
106
|
+
|
107
|
+
metrics.each_value do |metric_data|
|
108
|
+
row = build_metric_row(metric_data, timestamp, all_label_keys)
|
109
|
+
rows << row
|
110
|
+
end
|
111
|
+
|
112
|
+
# Generate CSV
|
113
|
+
CSV.generate(col_sep: @separator, row_sep: row_separator) do |csv|
|
114
|
+
rows.each { |row| csv << row }
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
# Extract all unique label keys from metrics
|
119
|
+
def extract_all_label_keys(metrics)
|
120
|
+
label_keys = Set.new
|
121
|
+
|
122
|
+
metrics.each_value do |metric_data|
|
123
|
+
labels = metric_data[:labels] || {}
|
124
|
+
label_keys.merge(labels.keys.map(&:to_s))
|
125
|
+
end
|
126
|
+
|
127
|
+
label_keys.to_a.sort
|
128
|
+
end
|
129
|
+
|
130
|
+
# Build CSV headers
|
131
|
+
def build_headers(label_keys)
|
132
|
+
headers = []
|
133
|
+
|
134
|
+
@columns.each do |column|
|
135
|
+
case column
|
136
|
+
when 'labels'
|
137
|
+
if @flatten_labels && label_keys.any?
|
138
|
+
headers.concat(label_keys.map { |key| "label_#{key}" })
|
139
|
+
else
|
140
|
+
headers << 'labels'
|
141
|
+
end
|
142
|
+
else
|
143
|
+
headers << column
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
headers
|
148
|
+
end
|
149
|
+
|
150
|
+
# Build a single metric row
|
151
|
+
def build_metric_row(metric_data, timestamp, label_keys)
|
152
|
+
row = []
|
153
|
+
labels = metric_data[:labels] || {}
|
154
|
+
|
155
|
+
@columns.each do |column|
|
156
|
+
case column
|
157
|
+
when 'timestamp'
|
158
|
+
row << timestamp
|
159
|
+
when 'name'
|
160
|
+
row << metric_data[:name]
|
161
|
+
when 'type'
|
162
|
+
row << metric_data[:type]
|
163
|
+
when 'value'
|
164
|
+
row << metric_data[:value]
|
165
|
+
when 'labels'
|
166
|
+
if @flatten_labels && label_keys.any?
|
167
|
+
# Add each label as separate column
|
168
|
+
label_keys.each do |key|
|
169
|
+
row << (labels[key.to_s] || labels[key.to_sym] || '')
|
170
|
+
end
|
171
|
+
else
|
172
|
+
# Add labels as JSON string
|
173
|
+
row << (labels.any? ? labels.to_json : '')
|
174
|
+
end
|
175
|
+
else
|
176
|
+
# Custom column - try to get from metric data
|
177
|
+
row << (metric_data[column.to_sym] || '')
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
row
|
182
|
+
end
|
183
|
+
|
184
|
+
# Return empty export result
|
185
|
+
def empty_export
|
186
|
+
{
|
187
|
+
success: true,
|
188
|
+
format: 'csv',
|
189
|
+
data: '',
|
190
|
+
size_bytes: 0,
|
191
|
+
metrics_count: 0,
|
192
|
+
rows: 0
|
193
|
+
}
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'base_exporter'
|
4
|
+
|
5
|
+
module Tasker
|
6
|
+
module Telemetry
|
7
|
+
module Plugins
|
8
|
+
# JSON format exporter for metrics data
|
9
|
+
#
|
10
|
+
# Exports metrics in structured JSON format with optional pretty printing
|
11
|
+
# and custom field mapping.
|
12
|
+
#
|
13
|
+
# @example Basic Usage
|
14
|
+
# exporter = Tasker::Telemetry::Plugins::JsonExporter.new
|
15
|
+
# result = exporter.export(metrics_data, pretty: true)
|
16
|
+
#
|
17
|
+
# @example With Custom Field Mapping
|
18
|
+
# exporter = Tasker::Telemetry::Plugins::JsonExporter.new(
|
19
|
+
# field_mapping: {
|
20
|
+
# timestamp: 'collected_at',
|
21
|
+
# metrics: 'data'
|
22
|
+
# }
|
23
|
+
# )
|
24
|
+
class JsonExporter < BaseExporter
|
25
|
+
VERSION = '1.0.0'
|
26
|
+
DESCRIPTION = 'JSON format exporter with customizable field mapping'
|
27
|
+
|
28
|
+
# @param options [Hash] Configuration options
|
29
|
+
# @option options [Hash] :field_mapping Custom field name mapping
|
30
|
+
# @option options [Boolean] :include_metadata Include export metadata
|
31
|
+
def initialize(options = {})
|
32
|
+
super()
|
33
|
+
@field_mapping = options.fetch(:field_mapping, {})
|
34
|
+
@include_metadata = options.fetch(:include_metadata, true)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Export metrics data as JSON
|
38
|
+
#
|
39
|
+
# @param metrics_data [Hash] Metrics data from MetricsBackend
|
40
|
+
# @param options [Hash] Export options
|
41
|
+
# @option options [Boolean] :pretty Pretty print JSON output
|
42
|
+
# @option options [Hash] :additional_fields Extra fields to include
|
43
|
+
# @return [Hash] Export result with JSON string
|
44
|
+
def export(metrics_data, options = {})
|
45
|
+
pretty = options.fetch(:pretty, false)
|
46
|
+
additional_fields = options.fetch(:additional_fields, {})
|
47
|
+
|
48
|
+
# Build export data with field mapping
|
49
|
+
export_data = build_export_data(metrics_data, additional_fields)
|
50
|
+
|
51
|
+
# Generate JSON
|
52
|
+
json_output = if pretty
|
53
|
+
JSON.pretty_generate(export_data)
|
54
|
+
else
|
55
|
+
JSON.generate(export_data)
|
56
|
+
end
|
57
|
+
|
58
|
+
{
|
59
|
+
success: true,
|
60
|
+
format: 'json',
|
61
|
+
data: json_output,
|
62
|
+
size_bytes: json_output.bytesize,
|
63
|
+
metrics_count: metrics_data[:metrics]&.size || 0
|
64
|
+
}
|
65
|
+
end
|
66
|
+
|
67
|
+
# Check if format is supported
|
68
|
+
#
|
69
|
+
# @param format [String, Symbol] Format to check
|
70
|
+
# @return [Boolean] True if JSON format is supported
|
71
|
+
def supports_format?(format)
|
72
|
+
%w[json].include?(format.to_s.downcase)
|
73
|
+
end
|
74
|
+
|
75
|
+
# Get supported formats
|
76
|
+
#
|
77
|
+
# @return [Array<String>] List of supported formats
|
78
|
+
def supported_formats
|
79
|
+
%w[json]
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
|
84
|
+
# Build export data structure with field mapping
|
85
|
+
def build_export_data(metrics_data, additional_fields)
|
86
|
+
export_data = {}
|
87
|
+
|
88
|
+
# Apply field mapping or use defaults
|
89
|
+
timestamp_field = @field_mapping.fetch(:timestamp, :timestamp)
|
90
|
+
metrics_field = @field_mapping.fetch(:metrics, :metrics)
|
91
|
+
total_metrics_field = @field_mapping.fetch(:total_metrics, :total_metrics)
|
92
|
+
|
93
|
+
# Core data
|
94
|
+
export_data[timestamp_field] = metrics_data[:timestamp]
|
95
|
+
export_data[metrics_field] = format_metrics(metrics_data[:metrics] || {})
|
96
|
+
export_data[total_metrics_field] = metrics_data[:total_metrics] || 0
|
97
|
+
|
98
|
+
# Add metadata if enabled
|
99
|
+
if @include_metadata
|
100
|
+
metadata_field = @field_mapping.fetch(:metadata, :metadata)
|
101
|
+
export_data[metadata_field] = {
|
102
|
+
exporter: 'json',
|
103
|
+
version: VERSION,
|
104
|
+
exported_at: Time.current.iso8601,
|
105
|
+
field_mapping: @field_mapping.any? ? @field_mapping : nil
|
106
|
+
}.compact
|
107
|
+
end
|
108
|
+
|
109
|
+
# Add additional fields
|
110
|
+
export_data.merge!(additional_fields) if additional_fields.any?
|
111
|
+
|
112
|
+
export_data
|
113
|
+
end
|
114
|
+
|
115
|
+
# Format metrics for JSON export
|
116
|
+
def format_metrics(metrics)
|
117
|
+
# Handle malformed input gracefully
|
118
|
+
return {} unless metrics.is_a?(Hash)
|
119
|
+
return {} if metrics.empty?
|
120
|
+
|
121
|
+
formatted = {}
|
122
|
+
|
123
|
+
metrics.each do |metric_name, metric_data|
|
124
|
+
# Ensure metric_data is a hash
|
125
|
+
next unless metric_data.is_a?(Hash)
|
126
|
+
|
127
|
+
formatted[metric_name] = {
|
128
|
+
name: metric_data[:name],
|
129
|
+
type: metric_data[:type],
|
130
|
+
value: metric_data[:value],
|
131
|
+
labels: metric_data[:labels] || {},
|
132
|
+
help: metric_data[:help]
|
133
|
+
}.compact
|
134
|
+
end
|
135
|
+
|
136
|
+
formatted
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
@@ -0,0 +1,249 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Tasker
|
4
|
+
module Telemetry
|
5
|
+
# Prometheus exporter for converting native metrics to Prometheus format
|
6
|
+
#
|
7
|
+
# This exporter transforms metrics from the MetricsBackend singleton into
|
8
|
+
# standard Prometheus text format for consumption by monitoring systems.
|
9
|
+
#
|
10
|
+
# @example Basic usage
|
11
|
+
# exporter = PrometheusExporter.new
|
12
|
+
# prometheus_text = exporter.export
|
13
|
+
#
|
14
|
+
# @example With custom backend
|
15
|
+
# exporter = PrometheusExporter.new(MetricsBackend.instance)
|
16
|
+
# prometheus_text = exporter.export
|
17
|
+
class PrometheusExporter
|
18
|
+
# Initialize exporter with optional metrics backend
|
19
|
+
#
|
20
|
+
# @param backend [MetricsBackend] The metrics backend to export from
|
21
|
+
def initialize(backend = nil)
|
22
|
+
@backend = backend || MetricsBackend.instance
|
23
|
+
end
|
24
|
+
|
25
|
+
# Export all metrics in Prometheus text format
|
26
|
+
#
|
27
|
+
# Returns metrics in the standard Prometheus exposition format as specified at:
|
28
|
+
# https://prometheus.io/docs/instrumenting/exposition_formats/
|
29
|
+
#
|
30
|
+
# @return [String] Prometheus format text
|
31
|
+
def export
|
32
|
+
return '' unless telemetry_enabled?
|
33
|
+
|
34
|
+
metrics_data = @backend.export
|
35
|
+
return '' if metrics_data[:metrics].empty?
|
36
|
+
|
37
|
+
output = []
|
38
|
+
output << export_metadata(metrics_data)
|
39
|
+
output << export_metrics(metrics_data[:metrics])
|
40
|
+
"#{output.flatten.compact.join("\n")}\n"
|
41
|
+
rescue StandardError => e
|
42
|
+
# Log error but don't fail the export
|
43
|
+
log_export_error(e)
|
44
|
+
export_error_metric(e)
|
45
|
+
end
|
46
|
+
|
47
|
+
# Export metrics with error handling
|
48
|
+
#
|
49
|
+
# @return [Hash] Export result with success status and data
|
50
|
+
def safe_export
|
51
|
+
{
|
52
|
+
success: true,
|
53
|
+
data: export,
|
54
|
+
timestamp: Time.current.iso8601,
|
55
|
+
total_metrics: @backend.export[:total_metrics] || 0
|
56
|
+
}
|
57
|
+
rescue StandardError => e
|
58
|
+
{
|
59
|
+
success: false,
|
60
|
+
error: e.message,
|
61
|
+
timestamp: Time.current.iso8601,
|
62
|
+
total_metrics: 0
|
63
|
+
}
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
# Export metadata and help text
|
69
|
+
#
|
70
|
+
# @param metadata [Hash] Metrics metadata
|
71
|
+
# @return [Array<String>] Prometheus metadata lines
|
72
|
+
def export_metadata(metadata)
|
73
|
+
lines = []
|
74
|
+
lines << '# Tasker metrics export'
|
75
|
+
lines << "# GENERATED #{metadata[:timestamp]}"
|
76
|
+
lines << "# TOTAL_METRICS #{metadata[:total_metrics]}"
|
77
|
+
lines << ''
|
78
|
+
lines
|
79
|
+
end
|
80
|
+
|
81
|
+
# Export all metrics by type
|
82
|
+
#
|
83
|
+
# @param metrics [Hash] Hash of metric name to metric data
|
84
|
+
# @return [Array<String>] Prometheus metric lines
|
85
|
+
def export_metrics(metrics)
|
86
|
+
lines = []
|
87
|
+
|
88
|
+
# Group metrics by type for better organization
|
89
|
+
counters = metrics.select { |_, data| data[:type] == :counter }
|
90
|
+
gauges = metrics.select { |_, data| data[:type] == :gauge }
|
91
|
+
histograms = metrics.select { |_, data| data[:type] == :histogram }
|
92
|
+
|
93
|
+
lines.concat(export_counters(counters)) if counters.any?
|
94
|
+
lines.concat(export_gauges(gauges)) if gauges.any?
|
95
|
+
lines.concat(export_histograms(histograms)) if histograms.any?
|
96
|
+
|
97
|
+
lines
|
98
|
+
end
|
99
|
+
|
100
|
+
# Export counter metrics
|
101
|
+
#
|
102
|
+
# @param counters [Hash] Counter metrics data
|
103
|
+
# @return [Array<String>] Prometheus counter lines
|
104
|
+
def export_counters(counters)
|
105
|
+
lines = []
|
106
|
+
counters.each do |name, data|
|
107
|
+
lines << ''
|
108
|
+
lines << "# HELP #{name} #{help_text_for(name, :counter)}"
|
109
|
+
lines << "# TYPE #{name} counter"
|
110
|
+
lines << format_metric_line(name, data[:value], data[:labels])
|
111
|
+
end
|
112
|
+
lines
|
113
|
+
end
|
114
|
+
|
115
|
+
# Export gauge metrics
|
116
|
+
#
|
117
|
+
# @param gauges [Hash] Gauge metrics data
|
118
|
+
# @return [Array<String>] Prometheus gauge lines
|
119
|
+
def export_gauges(gauges)
|
120
|
+
lines = []
|
121
|
+
gauges.each do |name, data|
|
122
|
+
lines << ''
|
123
|
+
lines << "# HELP #{name} #{help_text_for(name, :gauge)}"
|
124
|
+
lines << "# TYPE #{name} gauge"
|
125
|
+
lines << format_metric_line(name, data[:value], data[:labels])
|
126
|
+
end
|
127
|
+
lines
|
128
|
+
end
|
129
|
+
|
130
|
+
# Export histogram metrics
|
131
|
+
#
|
132
|
+
# @param histograms [Hash] Histogram metrics data
|
133
|
+
# @return [Array<String>] Prometheus histogram lines
|
134
|
+
def export_histograms(histograms)
|
135
|
+
lines = []
|
136
|
+
histograms.each do |name, data|
|
137
|
+
lines << ''
|
138
|
+
lines << "# HELP #{name} #{help_text_for(name, :histogram)}"
|
139
|
+
lines << "# TYPE #{name} histogram"
|
140
|
+
|
141
|
+
# Export histogram buckets
|
142
|
+
data[:buckets].each do |le, count|
|
143
|
+
bucket_labels = data[:labels].merge(le: le.to_s)
|
144
|
+
lines << format_metric_line("#{name}_bucket", count, bucket_labels)
|
145
|
+
end
|
146
|
+
|
147
|
+
# Export histogram sum and count
|
148
|
+
lines << format_metric_line("#{name}_sum", data[:sum], data[:labels])
|
149
|
+
lines << format_metric_line("#{name}_count", data[:count], data[:labels])
|
150
|
+
end
|
151
|
+
lines
|
152
|
+
end
|
153
|
+
|
154
|
+
# Format a single metric line
|
155
|
+
#
|
156
|
+
# @param name [String] Metric name
|
157
|
+
# @param value [Numeric] Metric value
|
158
|
+
# @param labels [Hash] Metric labels
|
159
|
+
# @return [String] Formatted Prometheus metric line
|
160
|
+
def format_metric_line(name, value, labels = {})
|
161
|
+
if labels.empty?
|
162
|
+
"#{name} #{value}"
|
163
|
+
else
|
164
|
+
label_string = format_labels(labels)
|
165
|
+
"#{name}{#{label_string}} #{value}"
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
# Format labels for Prometheus
|
170
|
+
#
|
171
|
+
# @param labels [Hash] Labels hash
|
172
|
+
# @return [String] Formatted label string
|
173
|
+
def format_labels(labels)
|
174
|
+
labels.map do |key, value|
|
175
|
+
# Escape backslashes first, then quotes in label values
|
176
|
+
escaped_value = value.to_s.gsub('\\', '\\\\').gsub('"', '\\"')
|
177
|
+
"#{key}=\"#{escaped_value}\""
|
178
|
+
end.join(',')
|
179
|
+
end
|
180
|
+
|
181
|
+
# Generate help text for metrics
|
182
|
+
#
|
183
|
+
# @param name [String] Metric name
|
184
|
+
# @param type [Symbol] Metric type
|
185
|
+
# @return [String] Help text
|
186
|
+
def help_text_for(name, type)
|
187
|
+
case name
|
188
|
+
when /task.*total/
|
189
|
+
'Total number of tasks processed'
|
190
|
+
when /task.*duration/
|
191
|
+
'Task execution duration in seconds'
|
192
|
+
when /step.*total/
|
193
|
+
'Total number of steps executed'
|
194
|
+
when /step.*duration/
|
195
|
+
'Step execution duration in seconds'
|
196
|
+
when /workflow.*total/
|
197
|
+
'Total number of workflow orchestrations'
|
198
|
+
when /event.*total/
|
199
|
+
'Total number of events published'
|
200
|
+
when /error.*total/
|
201
|
+
'Total number of errors encountered'
|
202
|
+
when /queue.*size/
|
203
|
+
'Current queue size'
|
204
|
+
when /active.*connections/
|
205
|
+
'Number of active connections'
|
206
|
+
else
|
207
|
+
"Tasker #{type} metric: #{name}"
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
# Check if telemetry is enabled
|
212
|
+
#
|
213
|
+
# @return [Boolean] True if telemetry is enabled
|
214
|
+
def telemetry_enabled?
|
215
|
+
return false unless defined?(Tasker.configuration)
|
216
|
+
|
217
|
+
Tasker.configuration.telemetry.metrics_enabled
|
218
|
+
end
|
219
|
+
|
220
|
+
# Log export error with structured logging
|
221
|
+
#
|
222
|
+
# @param error [StandardError] The error that occurred
|
223
|
+
def log_export_error(error)
|
224
|
+
return unless defined?(Rails) && Rails.logger
|
225
|
+
|
226
|
+
Rails.logger.error({
|
227
|
+
message: 'Prometheus export failed',
|
228
|
+
error: error.message,
|
229
|
+
backtrace: error.backtrace&.first(5),
|
230
|
+
timestamp: Time.current.iso8601,
|
231
|
+
component: 'prometheus_exporter'
|
232
|
+
}.to_json)
|
233
|
+
end
|
234
|
+
|
235
|
+
# Export error metric when export fails
|
236
|
+
#
|
237
|
+
# @param error [StandardError] The error that occurred
|
238
|
+
# @return [String] Error metric in Prometheus format
|
239
|
+
def export_error_metric(error)
|
240
|
+
timestamp = Time.current.to_f
|
241
|
+
<<~PROMETHEUS
|
242
|
+
# Export error fallback metric
|
243
|
+
# TYPE tasker_metrics_export_errors_total counter
|
244
|
+
tasker_metrics_export_errors_total{error="#{error.class.name}"} 1 #{timestamp}
|
245
|
+
PROMETHEUS
|
246
|
+
end
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end
|