From 8b2f2d86e965c1bb4b03e52fe64f580f71c21e98 Mon Sep 17 00:00:00 2001 From: dosymep Date: Fri, 27 Mar 2026 13:59:48 +0600 Subject: [PATCH 01/31] create dotnet api server with tests --- .dockerignore | 25 + .editorconfig | 231 ++++++++++ .env.example | 26 ++ .gitattributes | 64 +++ .github/workflows/build.yml | 63 +++ .github/workflows/release.yml | 104 +++++ .github/workflows/tests.yml | 41 ++ .gitignore | 426 +++++++++++++++++- CODE_OF_CONDUCT.md | 76 ++++ CONTRIBUTING.md | 1 + CREDITS.md | 3 + Directory.Build.props | 7 + Directory.Build.targets | 2 + Directory.Packages.props | 37 ++ LICENSE => LICENSE.md | 0 README.md | 275 ++++++++++- SECURITY.md | 22 + docker-compose.mongodb.yml | 26 ++ docker-compose.mssql.yml | 24 + docker-compose.oracle.yml | 28 ++ docker-compose.postgres.yml | 25 + docker-compose.sqlite.yml | 7 + docker-compose.yml | 12 + global.json | 10 + src/Telemetry.Api/.dockerignore | 25 + .../Application/DTOs/EngineInfoDto.cs | 40 ++ .../Application/DTOs/EventRecordDto.cs | 164 +++++++ src/Telemetry.Api/Application/DTOs/MetaDto.cs | 16 + .../Application/DTOs/ScriptRecordDto.cs | 186 ++++++++ .../Application/DTOs/StatusRecordDto.cs | 52 +++ .../Application/DTOs/TraceInfoDto.cs | 25 + .../Interfaces/IApplicationDbContext.cs | 63 +++ .../Application/Interfaces/IServiceInfo.cs | 20 + .../Mappings/TelemetryMappingExtensions.cs | 213 +++++++++ .../Application/Services/ServiceInfo.cs | 29 ++ src/Telemetry.Api/Dockerfile | 53 +++ src/Telemetry.Api/Domain/Models/EngineInfo.cs | 40 ++ .../Domain/Models/EventRecord.cs | 173 +++++++ src/Telemetry.Api/Domain/Models/MetaRecord.cs | 16 + .../Domain/Models/ScriptRecord.cs | 196 ++++++++ src/Telemetry.Api/Domain/Models/TraceInfo.cs | 25 + .../Persistence/ApplicationDbContext.cs | 210 +++++++++ .../DynamicDataBsonSerializer.cs | 25 + .../DynamicDataJsonConverter.cs | 22 + src/Telemetry.Api/Program.cs | 186 ++++++++ .../Properties/launchSettings.json | 23 + src/Telemetry.Api/Telemetry.Api.csproj | 50 ++ src/Telemetry.Api/Telemetry.Api.http | 74 +++ .../Web/Controllers/TelemetryController.cs | 144 ++++++ .../Middleware/ExceptionHandlingMiddleware.cs | 27 ++ .../appsettings.Development.json | 8 + src/Telemetry.Api/appsettings.json | 9 + .../20260330090657_InitOracle.Designer.cs | 271 +++++++++++ .../Migrations/20260330090657_InitOracle.cs | 90 ++++ .../ApplicationDbContextModelSnapshot.cs | 268 +++++++++++ .../Telemetry.Migrations.Oracle.csproj | 22 + .../20260330090711_InitPostgres.Designer.cs | 271 +++++++++++ .../Migrations/20260330090711_InitPostgres.cs | 90 ++++ .../ApplicationDbContextModelSnapshot.cs | 268 +++++++++++ .../Telemetry.Migrations.Postgres.csproj | 22 + .../20260330090733_InitSqlServer.Designer.cs | 271 +++++++++++ .../20260330090733_InitSqlServer.cs | 90 ++++ .../ApplicationDbContextModelSnapshot.cs | 268 +++++++++++ .../Telemetry.Migrations.SqlServer.csproj | 22 + .../20260330090723_InitSqlite.Designer.cs | 266 +++++++++++ .../Migrations/20260330090723_InitSqlite.cs | 90 ++++ .../ApplicationDbContextModelSnapshot.cs | 263 +++++++++++ .../Telemetry.Migrations.Sqlite.csproj | 22 + telemetry-server.slnx | 13 + .../BaseIntegrationTest.cs | 108 +++++ .../MongoDbIntegrationTests.cs | 67 +++ .../MsSqlIntegrationTests.cs | 66 +++ .../OracleIntegrationTests.cs | 66 +++ .../PostgresIntegrationTests.cs | 66 +++ .../SqliteIntegrationTests.cs | 65 +++ .../Telemetry.Api.IntegrationTests.csproj | 32 ++ .../TelemetryMappingExtensionsTests.cs | 306 +++++++++++++ .../Telemetry.Api.UnitTests.csproj | 25 + .../Controllers/TelemetryControllerTests.cs | 150 ++++++ 79 files changed, 7181 insertions(+), 26 deletions(-) create mode 100644 .dockerignore create mode 100644 .editorconfig create mode 100644 .env.example create mode 100644 .gitattributes create mode 100644 .github/workflows/build.yml create mode 100644 .github/workflows/release.yml create mode 100644 .github/workflows/tests.yml create mode 100644 CODE_OF_CONDUCT.md create mode 100644 CONTRIBUTING.md create mode 100644 CREDITS.md create mode 100644 Directory.Build.props create mode 100644 Directory.Build.targets create mode 100644 Directory.Packages.props rename LICENSE => LICENSE.md (100%) create mode 100644 SECURITY.md create mode 100644 docker-compose.mongodb.yml create mode 100644 docker-compose.mssql.yml create mode 100644 docker-compose.oracle.yml create mode 100644 docker-compose.postgres.yml create mode 100644 docker-compose.sqlite.yml create mode 100644 docker-compose.yml create mode 100644 global.json create mode 100644 src/Telemetry.Api/.dockerignore create mode 100644 src/Telemetry.Api/Application/DTOs/EngineInfoDto.cs create mode 100644 src/Telemetry.Api/Application/DTOs/EventRecordDto.cs create mode 100644 src/Telemetry.Api/Application/DTOs/MetaDto.cs create mode 100644 src/Telemetry.Api/Application/DTOs/ScriptRecordDto.cs create mode 100644 src/Telemetry.Api/Application/DTOs/StatusRecordDto.cs create mode 100644 src/Telemetry.Api/Application/DTOs/TraceInfoDto.cs create mode 100644 src/Telemetry.Api/Application/Interfaces/IApplicationDbContext.cs create mode 100644 src/Telemetry.Api/Application/Interfaces/IServiceInfo.cs create mode 100644 src/Telemetry.Api/Application/Mappings/TelemetryMappingExtensions.cs create mode 100644 src/Telemetry.Api/Application/Services/ServiceInfo.cs create mode 100644 src/Telemetry.Api/Dockerfile create mode 100644 src/Telemetry.Api/Domain/Models/EngineInfo.cs create mode 100644 src/Telemetry.Api/Domain/Models/EventRecord.cs create mode 100644 src/Telemetry.Api/Domain/Models/MetaRecord.cs create mode 100644 src/Telemetry.Api/Domain/Models/ScriptRecord.cs create mode 100644 src/Telemetry.Api/Domain/Models/TraceInfo.cs create mode 100644 src/Telemetry.Api/Infrastructure/Persistence/ApplicationDbContext.cs create mode 100644 src/Telemetry.Api/JsonConverters/DynamicDataBsonSerializer.cs create mode 100644 src/Telemetry.Api/JsonConverters/DynamicDataJsonConverter.cs create mode 100644 src/Telemetry.Api/Program.cs create mode 100644 src/Telemetry.Api/Properties/launchSettings.json create mode 100644 src/Telemetry.Api/Telemetry.Api.csproj create mode 100644 src/Telemetry.Api/Telemetry.Api.http create mode 100644 src/Telemetry.Api/Web/Controllers/TelemetryController.cs create mode 100644 src/Telemetry.Api/Web/Middleware/ExceptionHandlingMiddleware.cs create mode 100644 src/Telemetry.Api/appsettings.Development.json create mode 100644 src/Telemetry.Api/appsettings.json create mode 100644 src/Telemetry.Migrations.Oracle/Migrations/20260330090657_InitOracle.Designer.cs create mode 100644 src/Telemetry.Migrations.Oracle/Migrations/20260330090657_InitOracle.cs create mode 100644 src/Telemetry.Migrations.Oracle/Migrations/ApplicationDbContextModelSnapshot.cs create mode 100644 src/Telemetry.Migrations.Oracle/Telemetry.Migrations.Oracle.csproj create mode 100644 src/Telemetry.Migrations.Postgres/Migrations/20260330090711_InitPostgres.Designer.cs create mode 100644 src/Telemetry.Migrations.Postgres/Migrations/20260330090711_InitPostgres.cs create mode 100644 src/Telemetry.Migrations.Postgres/Migrations/ApplicationDbContextModelSnapshot.cs create mode 100644 src/Telemetry.Migrations.Postgres/Telemetry.Migrations.Postgres.csproj create mode 100644 src/Telemetry.Migrations.SqlServer/Migrations/20260330090733_InitSqlServer.Designer.cs create mode 100644 src/Telemetry.Migrations.SqlServer/Migrations/20260330090733_InitSqlServer.cs create mode 100644 src/Telemetry.Migrations.SqlServer/Migrations/ApplicationDbContextModelSnapshot.cs create mode 100644 src/Telemetry.Migrations.SqlServer/Telemetry.Migrations.SqlServer.csproj create mode 100644 src/Telemetry.Migrations.Sqlite/Migrations/20260330090723_InitSqlite.Designer.cs create mode 100644 src/Telemetry.Migrations.Sqlite/Migrations/20260330090723_InitSqlite.cs create mode 100644 src/Telemetry.Migrations.Sqlite/Migrations/ApplicationDbContextModelSnapshot.cs create mode 100644 src/Telemetry.Migrations.Sqlite/Telemetry.Migrations.Sqlite.csproj create mode 100644 telemetry-server.slnx create mode 100644 tests/Telemetry.Api.IntegrationTests/BaseIntegrationTest.cs create mode 100644 tests/Telemetry.Api.IntegrationTests/MongoDbIntegrationTests.cs create mode 100644 tests/Telemetry.Api.IntegrationTests/MsSqlIntegrationTests.cs create mode 100644 tests/Telemetry.Api.IntegrationTests/OracleIntegrationTests.cs create mode 100644 tests/Telemetry.Api.IntegrationTests/PostgresIntegrationTests.cs create mode 100644 tests/Telemetry.Api.IntegrationTests/SqliteIntegrationTests.cs create mode 100644 tests/Telemetry.Api.IntegrationTests/Telemetry.Api.IntegrationTests.csproj create mode 100644 tests/Telemetry.Api.UnitTests/Application/Mappings/TelemetryMappingExtensionsTests.cs create mode 100644 tests/Telemetry.Api.UnitTests/Telemetry.Api.UnitTests.csproj create mode 100644 tests/Telemetry.Api.UnitTests/Web/Controllers/TelemetryControllerTests.cs diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..af50df1 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,25 @@ +**/.dockerignore +**/.env +**/.git +**/.gitignore +**/.project +**/.settings +**/.toolstarget +**/.vs +**/.vscode +**/.idea +**/*.*proj.user +**/*.dbmdl +**/*.jfm +**/azds.yaml +**/bin +**/charts +**/docker-compose* +**/Dockerfile* +**/node_modules +**/npm-debug.log +**/obj +**/secrets.dev.yaml +**/values.dev.yaml +LICENSE +README.md \ No newline at end of file diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..ab4f3e0 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,231 @@ +# Remove the line below if you want to inherit .editorconfig settings from higher directories +root = true + +# C# files +[*.cs] + +#### Core EditorConfig Options #### + +# Indentation and spacing +indent_size = 4 +indent_style = space +tab_width = 4 + +# New line preferences +end_of_line = crlf +insert_final_newline = false + +#### .NET Coding Conventions #### + +# Organize usings +dotnet_separate_import_directive_groups = false +dotnet_sort_system_directives_first = false +file_header_template = unset + +# this. and Me. preferences +dotnet_style_qualification_for_event = false +dotnet_style_qualification_for_field = false +dotnet_style_qualification_for_method = false +dotnet_style_qualification_for_property = false + +# Language keywords vs BCL types preferences +dotnet_style_predefined_type_for_locals_parameters_members = true +dotnet_style_predefined_type_for_member_access = true + +# Parentheses preferences +dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity +dotnet_style_parentheses_in_other_operators = never_if_unnecessary +dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity + +# Modifier preferences +dotnet_style_require_accessibility_modifiers = for_non_interface_members + +# Expression-level preferences +dotnet_style_coalesce_expression = true +dotnet_style_collection_initializer = true +dotnet_style_explicit_tuple_names = true +dotnet_style_namespace_match_folder = true +dotnet_style_null_propagation = true +dotnet_style_object_initializer = true +dotnet_style_operator_placement_when_wrapping = beginning_of_line +dotnet_style_prefer_auto_properties = true +dotnet_style_prefer_collection_expression = when_types_loosely_match +dotnet_style_prefer_compound_assignment = true +dotnet_style_prefer_conditional_expression_over_assignment = true +dotnet_style_prefer_conditional_expression_over_return = true +dotnet_style_prefer_foreach_explicit_cast_in_source = when_strongly_typed +dotnet_style_prefer_inferred_anonymous_type_member_names = true +dotnet_style_prefer_inferred_tuple_names = true +dotnet_style_prefer_is_null_check_over_reference_equality_method = true +dotnet_style_prefer_simplified_boolean_expressions = true +dotnet_style_prefer_simplified_interpolation = true + +# Field preferences +dotnet_style_readonly_field = true + +# Parameter preferences +dotnet_code_quality_unused_parameters = all:silent + +# Suppression preferences +dotnet_remove_unnecessary_suppression_exclusions = none + +# New line preferences +dotnet_style_allow_multiple_blank_lines_experimental = true +dotnet_style_allow_statement_immediately_after_block_experimental = true + +#### C# Coding Conventions #### + +# var preferences +csharp_style_var_elsewhere = false +csharp_style_var_for_built_in_types = false +csharp_style_var_when_type_is_apparent = false + +# Expression-bodied members +csharp_style_expression_bodied_accessors = true +csharp_style_expression_bodied_constructors = false +csharp_style_expression_bodied_indexers = true +csharp_style_expression_bodied_lambdas = true +csharp_style_expression_bodied_local_functions = false +csharp_style_expression_bodied_methods = false +csharp_style_expression_bodied_operators = false +csharp_style_expression_bodied_properties = true + +# Pattern matching preferences +csharp_style_pattern_matching_over_as_with_null_check = true +csharp_style_pattern_matching_over_is_with_cast_check = true +csharp_style_prefer_extended_property_pattern = true +csharp_style_prefer_not_pattern = true +csharp_style_prefer_pattern_matching = true +csharp_style_prefer_switch_expression = true + +# Null-checking preferences +csharp_style_conditional_delegate_call = true + +# Modifier preferences +csharp_prefer_static_local_function = true +csharp_preferred_modifier_order = public, private, protected, internal, file, static, extern, new, virtual, abstract, sealed, override, readonly, unsafe, required, volatile, async +csharp_style_prefer_readonly_struct = true +csharp_style_prefer_readonly_struct_member = true + +# Code-block preferences +csharp_prefer_braces = true +csharp_prefer_simple_using_statement = true +csharp_style_namespace_declarations = block_scoped +csharp_style_prefer_method_group_conversion = true +csharp_style_prefer_primary_constructors = true +csharp_style_prefer_top_level_statements = true + +# Expression-level preferences +csharp_prefer_simple_default_expression = true +csharp_style_deconstructed_variable_declaration = true +csharp_style_implicit_object_creation_when_type_is_apparent = true +csharp_style_inlined_variable_declaration = true +csharp_style_prefer_index_operator = true +csharp_style_prefer_local_over_anonymous_function = true +csharp_style_prefer_null_check_over_type_check = true +csharp_style_prefer_range_operator = true +csharp_style_prefer_tuple_swap = true +csharp_style_prefer_utf8_string_literals = true +csharp_style_throw_expression = true +csharp_style_unused_value_assignment_preference = discard_variable +csharp_style_unused_value_expression_statement_preference = discard_variable + +# 'using' directive preferences +csharp_using_directive_placement = outside_namespace + +# New line preferences +csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true +csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = true +csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = true +csharp_style_allow_blank_lines_between_consecutive_braces_experimental = true +csharp_style_allow_embedded_statements_on_same_line_experimental = true + +#### C# Formatting Rules #### + +# New line preferences +csharp_new_line_before_catch = true +csharp_new_line_before_else = true +csharp_new_line_before_finally = true +csharp_new_line_before_members_in_anonymous_types = true +csharp_new_line_before_members_in_object_initializers = true +csharp_new_line_before_open_brace = all +csharp_new_line_between_query_expression_clauses = true + +# Indentation preferences +csharp_indent_block_contents = true +csharp_indent_braces = false +csharp_indent_case_contents = true +csharp_indent_case_contents_when_block = true +csharp_indent_labels = one_less_than_current +csharp_indent_switch_labels = true + +# Space preferences +csharp_space_after_cast = false +csharp_space_after_colon_in_inheritance_clause = true +csharp_space_after_comma = true +csharp_space_after_dot = false +csharp_space_after_keywords_in_control_flow_statements = true +csharp_space_after_semicolon_in_for_statement = true +csharp_space_around_binary_operators = before_and_after +csharp_space_around_declaration_statements = false +csharp_space_before_colon_in_inheritance_clause = true +csharp_space_before_comma = false +csharp_space_before_dot = false +csharp_space_before_open_square_brackets = false +csharp_space_before_semicolon_in_for_statement = false +csharp_space_between_empty_square_brackets = false +csharp_space_between_method_call_empty_parameter_list_parentheses = false +csharp_space_between_method_call_name_and_opening_parenthesis = false +csharp_space_between_method_call_parameter_list_parentheses = false +csharp_space_between_method_declaration_empty_parameter_list_parentheses = false +csharp_space_between_method_declaration_name_and_open_parenthesis = false +csharp_space_between_method_declaration_parameter_list_parentheses = false +csharp_space_between_parentheses = false +csharp_space_between_square_brackets = false + +# Wrapping preferences +csharp_preserve_single_line_blocks = true +csharp_preserve_single_line_statements = true + +#### Naming styles #### + +# Naming rules + +dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion +dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface +dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i + +dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.types_should_be_pascal_case.symbols = types +dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case + +dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members +dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case + +# Symbol specifications + +dotnet_naming_symbols.interface.applicable_kinds = interface +dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.interface.required_modifiers = + +dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum +dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.types.required_modifiers = + +dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method +dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.non_field_members.required_modifiers = + +# Naming styles + +dotnet_naming_style.pascal_case.required_prefix = +dotnet_naming_style.pascal_case.required_suffix = +dotnet_naming_style.pascal_case.word_separator = +dotnet_naming_style.pascal_case.capitalization = pascal_case + +dotnet_naming_style.begins_with_i.required_prefix = I +dotnet_naming_style.begins_with_i.required_suffix = +dotnet_naming_style.begins_with_i.word_separator = +dotnet_naming_style.begins_with_i.capitalization = pascal_case \ No newline at end of file diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..61f5471 --- /dev/null +++ b/.env.example @@ -0,0 +1,26 @@ +# App +ASPNETCORE_ENVIRONMENT=Development + +# Oracle +ORACLE_PASSWORD='8TYd50g*0trE' +ORACLE_APP_USER='oracle' +ORACLE_APP_USER_PASSWORD='9%8bphDFOj4P' + +# Postgres +POSTGRES_DB=telemetry +POSTGRES_USER='postgres' +POSTGRES_PASSWORD='iBT|vC857AoS' + +# MSSQL +MSSQL_ACCEPT_EULA=Y +MSSQL_DATABASE_NAME=telemetry +MSSQL_USER='sa' +MSSQL_SA_PASSWORD='AwbW~PNM3NxH' + +# SQLite +SQLITE_DATABASE_NAME=telemetry + +# MongoDB +MONGODB_DATABASE_NAME=telemetry +MONGODB_ROOT_USER='mongodb' +MONGODB_ROOT_PASSWORD='xF?iqMJhZj$R' \ No newline at end of file diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..1beb0d1 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,64 @@ + +############################################################################### +# Set default behavior to automatically normalize line endings. +############################################################################### +* text=auto + +############################################################################### +# Set default behavior for command prompt diff. +# +# This is need for earlier builds of msysgit that does not have it on by +# default for csharp files. +# Note: This is only used by command line +############################################################################### +#*.cs diff=csharp + +############################################################################### +# Set the merge driver for project and solution files +# +# Merging from the command prompt will add diff markers to the files if there +# are conflicts (Merging from VS is not affected by the settings below, in VS +# the diff markers are never inserted). Diff markers may cause the following +# file extensions to fail to load in VS. An alternative would be to treat +# these files as binary and thus will always conflict and require user +# intervention with every merge. To do so, just uncomment the entries below +############################################################################### +#*.sln merge=binary +#*.csproj merge=binary +#*.vbproj merge=binary +#*.vcxproj merge=binary +#*.vcproj merge=binary +#*.dbproj merge=binary +#*.fsproj merge=binary +#*.lsproj merge=binary +#*.wixproj merge=binary +#*.modelproj merge=binary +#*.sqlproj merge=binary +#*.wwaproj merge=binary + +############################################################################### +# behavior for image files +# +# image files are treated as binary by default. +############################################################################### +#*.jpg binary +#*.png binary +#*.gif binary + +############################################################################### +# diff behavior for common document formats +# +# Convert binary document formats to text before diffing them. This feature +# is only available from the command line. Turn it on by uncommenting the +# entries below. +############################################################################### +#*.doc diff=astextplain +#*.DOC diff=astextplain +#*.docx diff=astextplain +#*.DOCX diff=astextplain +#*.dot diff=astextplain +#*.DOT diff=astextplain +#*.pdf diff=astextplain +#*.PDF diff=astextplain +#*.rtf diff=astextplain +#*.RTF diff=astextplain diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..5108702 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,63 @@ +name: Tests + +on: + pull_request: + branches: [ main ] + +env: + BUILD_PATH: bin + BUILD_CONFIGURATION: Debug + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + + - name: Setup .NET + uses: actions/setup-dotnet@v5 + with: + dotnet-version: '10.0.x' + + - name: Restore dependencies + run: dotnet restore + + - name: Build + run: >- + dotnet build "./src/Telemetry.Api/Telemetry.Api.csproj" -c $BUILD_CONFIGURATION -o $BUILD_PATH + dotnet build "./src/Telemetry.Migrations.Oracle/Telemetry.Migrations.Oracle.csproj" -c $BUILD_CONFIGURATION -o $BUILD_PATH + dotnet build "./src/Telemetry.Migrations.Postgres/Telemetry.Migrations.Postgres.csproj" -c $BUILD_CONFIGURATION -o $BUILD_PATH + dotnet build "./src/Telemetry.Migrations.Sqlite/Telemetry.Migrations.Sqlite.csproj" -c $BUILD_CONFIGURATION -o $BUILD_PATH + dotnet build "./src/Telemetry.Migrations.SqlServer/Telemetry.Migrations.SqlServer.csproj" -c $BUILD_CONFIGURATION -o $BUILD_PATH + + + - name: Upload Build Results + uses: actions/upload-artifact@v7 + with: + name: build + path: ${BUILD_PATH} + + docker-publish: + runs-on: ubuntu-latest + steps: + - name: Generate version + run: echo "VERSION=2.0.0.${{ github.run_number }}-alpha" >> $GITHUB_ENV + + - name: Login to Docker Hub + uses: docker/login-action@v4 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Set up QEMU + uses: docker/setup-qemu-action@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v4 + + - name: Build and push + uses: docker/build-push-action@v7 + with: + push: true + context: src/Telemetry.Api + tags: pyrevitlabs/pyrevit-telemetry:${{ env.VERSION }} \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..fd7fb94 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,104 @@ +name: Tests + +on: + push: + branches: [ main ] + +env: + BUILD_PATH: /bin + BUILD_CONFIGURATION: Release + PUBLISH_PATH: /publish + MIGRATIONS_PATH: migrations + +jobs: + publish: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + + - name: Generate version + run: echo "VERSION=2.0.0.${{ github.run_number }}" >> $GITHUB_ENV + + - name: Setup .NET + uses: actions/setup-dotnet@v5 + with: + dotnet-version: '10.0.x' + + - name: Restore dependencies + run: dotnet restore + + - name: Build + run: >- + dotnet build "./src/Telemetry.Api/Telemetry.Api.csproj" -c $BUILD_CONFIGURATION -o $BUILD_PATH + dotnet build "./src/Telemetry.Migrations.Oracle/Telemetry.Migrations.Oracle.csproj" -c $BUILD_CONFIGURATION -o $BUILD_PATH + dotnet build "./src/Telemetry.Migrations.Postgres/Telemetry.Migrations.Postgres.csproj" -c $BUILD_CONFIGURATION -o $BUILD_PATH + dotnet build "./src/Telemetry.Migrations.Sqlite/Telemetry.Migrations.Sqlite.csproj" -c $BUILD_CONFIGURATION -o $BUILD_PATH + dotnet build "./src/Telemetry.Migrations.SqlServer/Telemetry.Migrations.SqlServer.csproj" -c $BUILD_CONFIGURATION -o $BUILD_PATH + + - name: Publish + run: >- + dotnet publish "./src/Telemetry.Api/Telemetry.Api.csproj" -c $BUILD_CONFIGURATION -o $PUBLISH_PATH + dotnet publish "./src/Telemetry.Migrations.Oracle/Telemetry.Migrations.Oracle.csproj" -c $BUILD_CONFIGURATION -o $MIGRATIONS_PATH/oracle + dotnet publish "./src/Telemetry.Migrations.Postgres/Telemetry.Migrations.Postgres.csproj" -c $BUILD_CONFIGURATION -o $MIGRATIONS_PATH/postgres + dotnet publish "./src/Telemetry.Migrations.Sqlite/Telemetry.Migrations.Sqlite.csproj" -c $BUILD_CONFIGURATION -o $MIGRATIONS_PATH/sqlite + dotnet publish "./src/Telemetry.Migrations.SqlServer/Telemetry.Migrations.SqlServer.csproj" -c $BUILD_CONFIGURATION -o $MIGRATIONS_PATH/sqlserver + + - name: Upload Publish Results + uses: actions/upload-artifact@v7 + with: + name: publish + path: >- + ${{ env.BUILD_PATH }}/*.* + ${{ env.MIGRATIONS_PATH }}/oracle/Telemetry.Migrations.Oracle.dll + ${{ env.MIGRATIONS_PATH }}/postgres/Telemetry.Migrations.Postgres.dll + ${{ env.MIGRATIONS_PATH }}/sqlite/Telemetry.Migrations.Sqlite.dll + ${{ env.MIGRATIONS_PATH }}/sqlserver/Telemetry.Migrations.SqlServer.dll + + - name: Publish Release + uses: softprops/action-gh-release@v2 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + draft: true + prerelease: false + body: dont forget fill changelog + tag_name: ${{ env.VERSION }} + name: pyrevit-telemetry ${{ env.VERSION }} + files: >- + ${{ env.BUILD_PATH }}/*.* + ${{ env.MIGRATIONS_PATH }}/oracle/Telemetry.Migrations.Oracle.dll + ${{ env.MIGRATIONS_PATH }}/postgres/Telemetry.Migrations.Postgres.dll + ${{ env.MIGRATIONS_PATH }}/sqlite/Telemetry.Migrations.Sqlite.dll + ${{ env.MIGRATIONS_PATH }}/sqlserver/Telemetry.Migrations.SqlServer.dll + + docker-publish: + runs-on: ubuntu-latest + steps: + - name: Generate version + run: echo "VERSION=2.0.0.${{ github.run_number }}" >> $GITHUB_ENV + + - name: Login to Docker Hub + uses: docker/login-action@v4 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Set up QEMU + uses: docker/setup-qemu-action@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v4 + + - name: Build and push + uses: docker/build-push-action@v7 + with: + push: true + context: src/Telemetry.Api + tags: pyrevitlabs/pyrevit-telemetry:latest + + - name: Build and push + uses: docker/build-push-action@v7 + with: + push: true + context: src/Telemetry.Api + tags: pyrevitlabs/pyrevit-telemetry:${{ env.VERSION }} \ No newline at end of file diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..3a0e801 --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,41 @@ +name: Tests + +on: + pull_request: + branches: [ main ] + +env: + BUILD_PATH: bin + BUILD_CONFIGURATION: Debug + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + + - name: Setup .NET + uses: actions/setup-dotnet@v5 + with: + dotnet-version: '10.0.x' + + - name: Restore dependencies + run: dotnet restore + + - name: Build + run: dotnet build --no-restore -c ${{ env.BUILD_CONFIGURATION }} + + - name: Set up QEMU + uses: docker/setup-qemu-action@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v4 + + - name: Test + run: dotnet test --no-build -c ${{ env.BUILD_CONFIGURATION }} + + - name: Upload Test Results + uses: actions/upload-artifact@v7 + with: + name: test-results + path: '**/TestResults/*.*' diff --git a/.gitignore b/.gitignore index 6f72f89..62da786 100644 --- a/.gitignore +++ b/.gitignore @@ -1,25 +1,403 @@ -# If you prefer the allow list template instead of the deny list, see community template: -# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore -# -# Binaries for programs and plugins -*.exe -*.exe~ -*.dll -*.so -*.dylib - -# Test binary, built with `go test -c` -*.test - -# Output of the go coverage tool, specifically when used with LiteIDE -*.out - -# Dependency directories (remove the comment below to include it) -# vendor/ - -# Go workspace file -go.work -go.work.sum - -# env file +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Oo]ut/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd + +# Default ignored files +/shelf/ +/workspace.xml + +# Rider ignored files +/.idea.dosymep.iml +/modules.xml +/projectSettingsUpdater.xml +/contentModel.xml + +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml + +# User specific +**/.idea/**/workspace.xml +**/.idea/**/tasks.xml +**/.idea/shelf/* +**/.idea/dictionaries +**/.idea/httpRequests/ + +# Sensitive or high-churn files +**/.idea/**/dataSources/ +**/.idea/**/dataSources.ids +**/.idea/**/dataSources.xml +**/.idea/**/dataSources.local.xml +**/.idea/**/sqlDataSources.xml +**/.idea/**/dynamic.xml + +# Rider +# Rider auto-generates .iml files, and contentModel.xml +**/.idea/**/*.iml +**/.idea/**/contentModel.xml +**/.idea/**/modules.xml + +/.idea +/mongodb .env +/telemetry-db \ No newline at end of file diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..0fa13a8 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,76 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, sex characteristics, gender identity and expression, +level of experience, education, socio-economic status, nationality, personal +appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or + advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at hello@pyrevitlabs.io. All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see +https://www.contributor-covenant.org/faq \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..cb960b4 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1 @@ +[See Contributing to pyRevit Source on pyRevit Wiki](https://pyrevitlabs.notion.site/Contributing-to-pyRevit-Source-6d25a5ac62c44bd9a0e9aefb8debefa2?pvs=4) \ No newline at end of file diff --git a/CREDITS.md b/CREDITS.md new file mode 100644 index 0000000..964d749 --- /dev/null +++ b/CREDITS.md @@ -0,0 +1,3 @@ +## Credits + +[See Credits Here](http://credits.pyrevitlabs.io) \ No newline at end of file diff --git a/Directory.Build.props b/Directory.Build.props new file mode 100644 index 0000000..0d3e88d --- /dev/null +++ b/Directory.Build.props @@ -0,0 +1,7 @@ + + + 2.0.0 + 2.0.0.0 + 2.0.0.0 + + \ No newline at end of file diff --git a/Directory.Build.targets b/Directory.Build.targets new file mode 100644 index 0000000..c1df222 --- /dev/null +++ b/Directory.Build.targets @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/Directory.Packages.props b/Directory.Packages.props new file mode 100644 index 0000000..7d0e493 --- /dev/null +++ b/Directory.Packages.props @@ -0,0 +1,37 @@ + + + true + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/LICENSE b/LICENSE.md similarity index 100% rename from LICENSE rename to LICENSE.md diff --git a/README.md b/README.md index 3e09386..0a90a88 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,273 @@ -# telemetry-server -Telemetry Server for pyRevit +# Telemetry Server for pyRevit + +A high-performance .NET 10 Web API service designed to collect and store telemetry data +from [pyRevit](https://github.com/pyrevitlabs/pyRevit). It supports multiple database providers and can be easily +deployed using Docker. + +## Project Structure + +The project follows a Clean Architecture approach: + +- **src/Telemetry.Api**: Main application source code. + - **Application**: Business logic, DTOs, mappings, and service interfaces. + - **Domain**: Core domain models and entities. + - **Infrastructure**: Database persistence, Entity Framework Core contexts, and external service implementations. + - **Web**: ASP.NET Core controllers, middleware, and API configuration. +- **src/Telemetry.Migrations.***: Separate projects for Entity Framework Core migrations (PostgreSQL, SQL Server, SQLite, Oracle). +- **tests**: Comprehensive test suite using [TUnit](https://github.com/thomhurst/TUnit). + - **Telemetry.Api.UnitTests**: Isolated tests for business logic and mappings. + - **Telemetry.Api.IntegrationTests**: End-to-end tests for API endpoints and database interactions. +- **telemetry-db**: Local directory for database persistence (used by Docker). + +## Prerequisites + +- [.NET 10 SDK](https://dotnet.microsoft.com/download/dotnet/10.0) +- [Docker](https://www.docker.com/get-started) and [Docker Compose](https://docs.docker.com/compose/install/) + +## Compilation + +To build the project locally, run the following command from the root directory: + +```bash +dotnet build telemetry-server.slnx +``` + +To run the application: + +```bash +dotnet run --project src/Telemetry.Api/Telemetry.Api.csproj +``` + +## Docker Deployment + +The project provides several Docker Compose configurations to support different database backends. + +### General Usage + +To start the API using the pre-built image, you can pull the latest version: + +```bash +docker pull pyrevit-telemetry:latest +``` + +To start the API with a specific database, use the following command structure: + +```bash +docker compose -f docker-compose.yml -f docker-compose..yml up -d +``` + +### Supported Database Variants + +| Database | Command | +|:---------------|:----------------------------------------------------------------------------| +| **PostgreSQL** | `docker compose -f docker-compose.yml -f docker-compose.postgres.yml up -d` | +| **SQL Server** | `docker compose -f docker-compose.yml -f docker-compose.mssql.yml up -d` | +| **SQLite** | `docker compose -f docker-compose.yml -f docker-compose.sqlite.yml up -d` | +| **Oracle** | `docker compose -f docker-compose.yml -f docker-compose.oracle.yml up -d` | +| **MongoDB** | `docker compose -f docker-compose.yml -f docker-compose.mongodb.yml up -d` | + +> ❗IMPORTANT +> - **MySQL**: Support is currently unavailable because the necessary Entity Framework Core libraries have not yet been ported to .NET 10. +> - **SQL Server & Oracle**: While these providers are implemented, they have not been fully tested in a .NET 10 environment. Full verification and ongoing support for these databases are left to the community. + +### Environment Variables + +Each database variant requires specific environment variables (usually defined in a `.env` file or passed directly). Key +variables include: + +- `DbProvider`: Specifies the database provider (e.g., `postgres`, `mssql`, `sqlite`, `oracle`, `mongodb`). +- `ConnectionStrings__DefaultConnection`: The connection string for the selected database. +- `ASPNETCORE_HTTP_PORTS`: The port the API listens to on (default: `8080`). + +## API Endpoints + +The API is versioned (currently `v2`). + +- `POST /api/v2/scripts`: Submit pyRevit script execution telemetry. +- `POST /api/v2/events`: Submit pyRevit event telemetry. +- `GET /api/v2/status`: Check service and database connection status. +- `GET /metrics`: Prometheus metrics for monitoring. +- `GET /swagger`: OpenAPI/Swagger documentation (in Development mode). + +## API Documentation + +When running in **Development** mode, the application provides interactive API documentation using [Swagger (OpenAPI)](https://swagger.io/). + +To access the Swagger UI: +1. Start the application in Development mode (`ASPNETCORE_ENVIRONMENT=Development`). +2. Navigate to `http://localhost:8080/swagger` (or your configured port). + +From the Swagger UI, you can explore all available endpoints, view request/response schemas, and test the API directly from your browser. + +## Monitoring + +The application exposes Prometheus metrics at the `/metrics` endpoint. This can be used to monitor the service's health, request rates, and performance using [Prometheus](https://prometheus.io/) and [Grafana](https://grafana.com/). + +To view the metrics: +1. Start the application. +2. Navigate to `http://localhost:8080/metrics` (or your configured port). + +## Testing + +The project uses [TUnit](https://github.com/thomhurst/TUnit), a modern testing framework for .NET, taking advantage of +the latest features in .NET 10. + +### Unit Tests + +Unit tests focus on isolated business logic and data mappings. They do not require any external dependencies. + +To run unit tests: + +```bash +dotnet run --project tests/Telemetry.Api.UnitTests/Telemetry.Api.UnitTests.csproj +``` + +### Integration Tests + +Integration tests verify the end-to-end functionality of the API, including database persistence. These tests +use [Testcontainers](https://testcontainers.com/) to spin up actual database instances (except for SQLite) during the +test execution. + +**Prerequisites:** Docker must be running on your machine to execute integration tests for PostgreSQL, SQL Server, +Oracle, and MongoDB. + +To run integration tests: + +```bash +dotnet run --project tests/Telemetry.Api.IntegrationTests/Telemetry.Api.IntegrationTests.csproj +``` + +## Manual Deployment (Without Docker) + +To run the server manually, follow these steps to build, configure, and publish the application. + +### Build and Publish + +1. **Publish the project:** + Run the following command to create a self-contained or framework-dependent deployment: + + ```bash + dotnet publish src/Telemetry.Api/Telemetry.Api.csproj -c Release -o ./publish + ``` + +2. **Navigate to the publish directory:** + + ```bash + cd ./publish + ``` + +### Configuration (appsettings.json) + +Before running the server, you must configure the database provider and connection string in `appsettings.json`. + +1. **Open `appsettings.json`** and add the following configuration: + + ```json + { + "DbProvider": "postgres", + "ConnectionStrings": { + "DefaultConnection": "Host=localhost;Database=telemetry;Username=postgres;Password=password" + }, + "MongoDbDatabaseName": "telemetry", + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" + } + ``` + +2. **Configuration Options:** + - `DbProvider`: Set to one of `postgres`, `mssql`, `sqlite`, `oracle`, `mongodb`. + - `ConnectionStrings:DefaultConnection`: Provide the appropriate connection string for your database. + - `MongoDbDatabaseName`: (Optional) Required only if using `mongodb`. + +### Running the Server + +Start the application using the `dotnet` CLI: + +```bash +dotnet Telemetry.Api.dll +``` + +The server will start and listen on the default ports (usually `http://localhost:5000` or as configured via environment variables). + +## Database Migrations + +The project uses Entity Framework Core (EF Core) to manage relational database schemas (PostgreSQL, SQL Server, SQLite, Oracle). + +### Prerequisites + +You need the `dotnet-ef` tool installed globally: + +```bash +dotnet tool install --global dotnet-ef +``` + +### Creating a New Migration + +If you modify the data models in the `Domain` or `Infrastructure` layers, you need to generate a new migration for each supported database provider. Each database has its own project for migrations. + +To generate migrations correctly, set the required environment variables for the target database and run the `dotnet ef migrations add` command from the root directory. + +#### Oracle +```bash +DbProvider=oracle ConnectionStrings__DefaultConnection="Data Source=localhost:1521/xe;User Id=test;Password=test" \ +dotnet ef migrations add \ + --project src/Telemetry.Migrations.Oracle \ + --startup-project src/Telemetry.Api \ + --context ApplicationDbContext +``` + +#### PostgreSQL +```bash +DbProvider=postgres ConnectionStrings__DefaultConnection="Host=localhost;Database=test;Username=test;Password=test" \ +dotnet ef migrations add \ + --project src/Telemetry.Migrations.Postgres \ + --startup-project src/Telemetry.Api \ + --context ApplicationDbContext +``` + +#### SQLite +```bash +DbProvider=sqlite ConnectionStrings__DefaultConnection="Data Source=/app/data/telemetry.db" \ +dotnet ef migrations add \ + --project src/Telemetry.Migrations.Sqlite \ + --startup-project src/Telemetry.Api \ + --context ApplicationDbContext +``` + +#### SQL Server +```bash +DbProvider=mssql ConnectionStrings__DefaultConnection="Server=localhost;Database=test;User Id=sa;Password=test" \ +dotnet ef migrations add \ + --project src/Telemetry.Migrations.SqlServer \ + --startup-project src/Telemetry.Api \ + --context ApplicationDbContext +``` + +### Reviewing the generated files + +New migration files will be created in their respective projects under the `Migrations` directory (e.g., `src/Telemetry.Migrations.Postgres/Migrations`). + +### Applying Migrations + +- **Automatic:** The server automatically applies pending migrations on startup for all relational database providers. +- **Manual:** You can manually update the database using the following command (example for SQLite): + + ```bash + DbProvider=sqlite ConnectionStrings__DefaultConnection="Data Source=/app/data/telemetry.db" \ + dotnet ef database update \ + --project src/Telemetry.Migrations.Sqlite \ + --startup-project src/Telemetry.Api \ + --context ApplicationDbContext + ``` + +> ❗NOTE +> **MongoDB** does not use EF Core migrations. Changes to the MongoDB data structure are handled by the application at runtime (schema-less or through driver-level configuration). + +## License + +This project is licensed under the terms of the license included in the root directory. diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..1f4d26f --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,22 @@ +# Security Policy + +> Note that the most up to date code is located in the develop branch. Every 6 months to 12 months, the develop branch +> is merged to the master branch and new releases are integrated. + +## Reporting a Vulnerability + +**Please do not report security vulnerabilities through public pyRevit GitHub issues, discussions, or pull requests.** + +Instead, please send an email to eirannejad+pyrevitsecurity[@]gmail.com . + +Please include as much of the information listed below as you can to help us better understand and resolve the issue: + +- The type of issue (e.g., buffer overflow, SQL injection, or cross-site scripting) +- Full paths of source file(s) related to the manifestation of the issue +- The location of the affected source code (tag/branch/commit or direct URL) +- Any special configuration required to reproduce the issue +- Step-by-step instructions to reproduce the issue +- Proof-of-concept or exploit code (if possible) +- Impact of the issue, including how an attacker might exploit the issue + +This information will help us triage your report more quickly. \ No newline at end of file diff --git a/docker-compose.mongodb.yml b/docker-compose.mongodb.yml new file mode 100644 index 0000000..e00011b --- /dev/null +++ b/docker-compose.mongodb.yml @@ -0,0 +1,26 @@ +services: + telemetry-api: + environment: + - DbProvider=mongodb + - MongoDbDatabaseName=${MONGODB_DATABASE_NAME} + - ConnectionStrings__DefaultConnection=mongodb://${MONGODB_ROOT_USER}:${MONGODB_ROOT_PASSWORD}@telemetry-db:27017 + depends_on: + telemetry-db: + condition: service_healthy + + telemetry-db: + image: mongo:8.2 + container_name: telemetry-db + environment: + - MONGO_INITDB_ROOT_USERNAME=${MONGODB_ROOT_USER} + - MONGO_INITDB_ROOT_PASSWORD=${MONGODB_ROOT_PASSWORD} + - MONGO_INITDB_DATABASE=${MONGODB_DATABASE_NAME} + ports: + - "27017:27017" + volumes: + - ./telemetry-db/mongodb:/data/db + healthcheck: + test: [ "CMD", "mongosh", "--quiet", "--eval", "'quit(db.runCommand({ ping: 1 }).ok ? 0 : 2)'" ] + interval: 10s + timeout: 5s + retries: 5 \ No newline at end of file diff --git a/docker-compose.mssql.yml b/docker-compose.mssql.yml new file mode 100644 index 0000000..0ed4022 --- /dev/null +++ b/docker-compose.mssql.yml @@ -0,0 +1,24 @@ +services: + telemetry-api: + environment: + - DbProvider=mssql + - ConnectionStrings__DefaultConnection=Server=telemetry-db;Database=${MSSQL_DATABASE_NAME};User Id=${MSSQL_USER};Password=${MSSQL_SA_PASSWORD};TrustServerCertificate=True; + depends_on: + telemetry-db: + condition: service_healthy + + telemetry-db: + container_name: telemetry-db + image: mcr.microsoft.com/mssql/server:2025-latest + environment: + - ACCEPT_EULA=${MSSQL_ACCEPT_EULA} + - MSSQL_SA_PASSWORD=${MSSQL_SA_PASSWORD} + volumes: + - ./telemetry-db/mssql:/var/opt/mssql + ports: + - "1433:1433" + healthcheck: + test: [ "CMD-SHELL", "/opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P '${MSSQL_SA_PASSWORD}' -Q 'SELECT 1' -C" ] + interval: 10s + timeout: 5s + retries: 5 diff --git a/docker-compose.oracle.yml b/docker-compose.oracle.yml new file mode 100644 index 0000000..39c88ee --- /dev/null +++ b/docker-compose.oracle.yml @@ -0,0 +1,28 @@ +services: + telemetry-api: + environment: + - DbProvider=oracle + - ConnectionStrings__DefaultConnection=User Id=${ORACLE_APP_USER};Password=${ORACLE_APP_USER_PASSWORD};Data Source=telemetry-db:1521/FREEPDB1; + depends_on: + telemetry-db: + condition: service_healthy + + telemetry-db: + container_name: telemetry-db + image: gvenzl/oracle-free:23-slim + + environment: + - ORACLE_PASSWORD=${ORACLE_PASSWORD} + - APP_USER=${ORACLE_APP_USER} + - APP_USER_PASSWORD=${ORACLE_APP_USER_PASSWORD} + volumes: + - ./telemetry-db/oracle:/opt/oracle/oradata + ports: + - "1521:1521" + healthcheck: + test: [ "CMD", "healthcheck.sh" ] + interval: 10s + timeout: 5s + retries: 10 + start_period: 5s + start_interval: 5s diff --git a/docker-compose.postgres.yml b/docker-compose.postgres.yml new file mode 100644 index 0000000..b18de98 --- /dev/null +++ b/docker-compose.postgres.yml @@ -0,0 +1,25 @@ +services: + telemetry-api: + environment: + - DbProvider=postgres + - ConnectionStrings__DefaultConnection=Host=telemetry-db;Database=${POSTGRES_DB};Username=${POSTGRES_USER};Password=${POSTGRES_PASSWORD} + depends_on: + telemetry-db: + condition: service_healthy + + telemetry-db: + container_name: telemetry-db + image: postgres:18-alpine + environment: + - POSTGRES_DB=${POSTGRES_DB} + - POSTGRES_USER=${POSTGRES_USER} + - POSTGRES_PASSWORD=${POSTGRES_PASSWORD} + volumes: + - ./telemetry-db/postgres:/var/lib/postgresql + ports: + - "5432:5432" + healthcheck: + test: [ "CMD-SHELL", "pg_isready -d ${POSTGRES_DB} -U ${POSTGRES_USER}" ] + interval: 10s + timeout: 5s + retries: 5 diff --git a/docker-compose.sqlite.yml b/docker-compose.sqlite.yml new file mode 100644 index 0000000..6b6e909 --- /dev/null +++ b/docker-compose.sqlite.yml @@ -0,0 +1,7 @@ +services: + telemetry-api: + environment: + - DbProvider=sqlite + - ConnectionStrings__DefaultConnection=Data Source=/app/data/${SQLITE_DATABASE_NAME}.db + volumes: + - ./telemetry-db/sqlite:/app/data diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..7827181 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,12 @@ +services: + telemetry-api: + container_name: telemetry-api + image: pyrevit-telemetry:latest + build: + context: . + dockerfile: src/Telemetry.Api/Dockerfile + ports: + - "8080:8080" + environment: + - ASPNETCORE_HTTP_PORTS=8080 + - ASPNETCORE_ENVIRONMENT=${ASPNETCORE_ENVIRONMENT} diff --git a/global.json b/global.json new file mode 100644 index 0000000..17d00dc --- /dev/null +++ b/global.json @@ -0,0 +1,10 @@ +{ + "sdk": { + "version": "10.0.0", + "rollForward": "latestMajor", + "allowPrerelease": true + }, + "test": { + "runner": "Microsoft.Testing.Platform" + } +} \ No newline at end of file diff --git a/src/Telemetry.Api/.dockerignore b/src/Telemetry.Api/.dockerignore new file mode 100644 index 0000000..af50df1 --- /dev/null +++ b/src/Telemetry.Api/.dockerignore @@ -0,0 +1,25 @@ +**/.dockerignore +**/.env +**/.git +**/.gitignore +**/.project +**/.settings +**/.toolstarget +**/.vs +**/.vscode +**/.idea +**/*.*proj.user +**/*.dbmdl +**/*.jfm +**/azds.yaml +**/bin +**/charts +**/docker-compose* +**/Dockerfile* +**/node_modules +**/npm-debug.log +**/obj +**/secrets.dev.yaml +**/values.dev.yaml +LICENSE +README.md \ No newline at end of file diff --git a/src/Telemetry.Api/Application/DTOs/EngineInfoDto.cs b/src/Telemetry.Api/Application/DTOs/EngineInfoDto.cs new file mode 100644 index 0000000..4ef8e30 --- /dev/null +++ b/src/Telemetry.Api/Application/DTOs/EngineInfoDto.cs @@ -0,0 +1,40 @@ +using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; + +namespace Telemetry.Api.Application.DTOs +{ + /// + /// Script engine information. + /// + public class EngineInfoDto + { + /// + /// Engine type name. + ///
Engine types. + ///
+ [MaxLength(100)] + [JsonPropertyName("type")] + public required string Type { get; init; } + + /// + /// Engine version. + ///
Engines list. + ///
+ [MaxLength(100)] + [JsonPropertyName("version")] + public required string Version { get; init; } + + /// + /// System paths using by script. + /// + [JsonPropertyName("syspath")] + public string[]? SysPath { get; init; } + + /// + /// Dynamic script configs data. + /// + [MaxLength(8000)] + [JsonPropertyName("configs")] + public string? Configs { get; init; } + } +} \ No newline at end of file diff --git a/src/Telemetry.Api/Application/DTOs/EventRecordDto.cs b/src/Telemetry.Api/Application/DTOs/EventRecordDto.cs new file mode 100644 index 0000000..02fa383 --- /dev/null +++ b/src/Telemetry.Api/Application/DTOs/EventRecordDto.cs @@ -0,0 +1,164 @@ +using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; + +namespace Telemetry.Api.Application.DTOs +{ + /// + /// Event record information. + /// + public class EventRecordDto + { + /// + /// Unique event id. + /// + [JsonPropertyName("handler_id")] + public required Guid HandlerId { get; init; } + + /// + /// Information about telemetry record. + /// + [JsonPropertyName("meta")] + public required MetaDto Meta { get; init; } + + /// + /// Event type name. + /// + [MaxLength(100)] + [JsonPropertyName("type")] + public required string EventType { get; init; } + + /// + /// Revit event + /// status. + /// + [MaxLength(100)] + [JsonPropertyName("status")] + public string? Status { get; init; } + + /// + /// When event started. + /// + [JsonPropertyName("timestamp")] + public required DateTimeOffset Timestamp { get; init; } + + /// + /// Username + /// who use Autodesk Revit (sets in options). + /// + [MaxLength(100)] + [JsonPropertyName("username")] + public required string Username { get; init; } + + /// + /// Username + /// who logged in Windows. + /// + [MaxLength(100)] + [JsonPropertyName("host_user")] + public string? HostUsername { get; init; } + + /// + /// Internal + /// build number + /// of the Autodesk Revit application. + /// + [MaxLength(100)] + [JsonPropertyName("revitbuild")] + public required string RevitBuild { get; init; } + + /// + /// Return the + /// primary version + /// of the Revit application. + /// + [MaxLength(100)] + [JsonPropertyName("revit")] + public required string RevitVersion { get; init; } + + /// + /// If event was cancelled , otherwise . + ///
RevitAPIEventArgs + /// IsCancelled method. + ///
+ [JsonPropertyName("cancelled")] + public bool? Cancelled { get; init; } + + /// + /// If event can cancel , otherwise . + ///
RevitAPIEventArgs + /// Cancellable property. + ///
+ [JsonPropertyName("cancellable")] + public bool? Cancellable { get; init; } + + /// + /// Id of the document that has just been closed. + ///
DocumentClosingEventArgs + /// DocumentId property. + ///
DocumentClosedEventArgs + /// DocumentId property. + ///
+ [JsonPropertyName("docid")] + public int DocumentId { get; init; } + + /// + /// Type of the document, e.g. Project or Template. + ///
DocumentType + /// enumeration. + ///
DocumentOpeningEventArgs + /// DocumentType property. + ///
DocumentCreatingEventArgs + /// DocumentType property. + ///
+ [MaxLength(100)] + [JsonPropertyName("doctype")] + public string? DocumentType { get; init; } + + /// + /// Document template name. + ///
DocumentCreatingEventArgs + /// Template property. + ///
+ [MaxLength(100)] + [JsonPropertyName("doctemplate")] + public string? DocumentTemplate { get; init; } + + /// + /// Document Title property. + /// + [MaxLength(250)] + [JsonPropertyName("docname")] + public string? DocumentName { get; init; } + + /// + /// Document PathName + /// property. + /// + [MaxLength(1024)] + [JsonPropertyName("docpath")] + public string? DocumentPath { get; init; } + + /// + /// Project name + /// (BuiltInParameter.PROJECT_NAME). + /// + [MaxLength(250)] + [JsonPropertyName("projectname")] + public string? ProjectName { get; init; } + + /// + /// Project number + /// (BuiltInParameter.PROJECT_NUMBER). + /// + [MaxLength(100)] + [JsonPropertyName("projectnum")] + public string? ProjectNum { get; init; } + + /// + /// Dynamic event args data. + /// + [MaxLength(8000)] + [JsonPropertyName("args")] + public string? EventArgs { get; init; } + } +} \ No newline at end of file diff --git a/src/Telemetry.Api/Application/DTOs/MetaDto.cs b/src/Telemetry.Api/Application/DTOs/MetaDto.cs new file mode 100644 index 0000000..a71058e --- /dev/null +++ b/src/Telemetry.Api/Application/DTOs/MetaDto.cs @@ -0,0 +1,16 @@ +using System.Text.Json.Serialization; + +namespace Telemetry.Api.Application.DTOs +{ + /// + /// Record metadata. + /// + public class MetaDto + { + /// + /// Schema version. + /// + [JsonPropertyName("schema")] + public required Version SchemaVersion { get; init; } + } +} \ No newline at end of file diff --git a/src/Telemetry.Api/Application/DTOs/ScriptRecordDto.cs b/src/Telemetry.Api/Application/DTOs/ScriptRecordDto.cs new file mode 100644 index 0000000..0949f88 --- /dev/null +++ b/src/Telemetry.Api/Application/DTOs/ScriptRecordDto.cs @@ -0,0 +1,186 @@ +using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; + +namespace Telemetry.Api.Application.DTOs +{ + /// + /// Script record information. + /// + public class ScriptRecordDto + { + /// + /// Unique session id (created when revit is opened). + /// + [JsonPropertyName("sessionid")] + public required Guid SessionId { get; init; } + + /// + /// Information about telemetry record. + /// + [JsonPropertyName("meta")] + public required MetaDto Meta { get; init; } + + /// + /// When script started. + /// + [JsonPropertyName("timestamp")] + public required DateTimeOffset Timestamp { get; init; } + + /// + /// Username + /// who use Autodesk Revit (sets in options). + /// + [MaxLength(100)] + [JsonPropertyName("username")] + public required string Username { get; init; } + + /// + /// Username + /// who logged in Windows. + /// + [MaxLength(100)] + [JsonPropertyName("host_user")] + public string? HostUsername { get; init; } + + /// + /// Internal + /// build number + /// of the Autodesk Revit application. + /// + [MaxLength(100)] + [JsonPropertyName("revitbuild")] + public required string RevitBuild { get; init; } + + /// + /// Return the + /// primary version + /// of the Revit application. + /// + [MaxLength(100)] + [JsonPropertyName("revit")] + public required string RevitVersion { get; init; } + + /// + /// pyrevit build version. + /// + [MaxLength(100)] + [JsonPropertyName("pyrevit")] + public required string PyRevitVersion { get; init; } + + /// + /// pyrevit + /// clone name. + /// + [MaxLength(100)] + [JsonPropertyName("clone")] + public required string CloneName { get; init; } + + /// + /// pyrevit + /// + /// debug + /// mode + /// . + /// + [JsonPropertyName("debug")] + public bool IsDebug { get; init; } + + /// + /// pyrevit + /// config mode. + /// + [JsonPropertyName("config")] + public bool IsConfig { get; init; } + + /// + /// If script was run from GUI (Click Revit Ribbon) , otherwise . + /// + [JsonPropertyName("from_gui")] + public bool IsExecFromGui { get; init; } + + /// + /// Unique execution id. + /// + [MaxLength(100)] + [JsonPropertyName("exec_id")] + public required string ExecId { get; init; } + + /// + /// When script executed. + /// + [JsonPropertyName("exec_timestamp")] + public required DateTimeOffset ExecTimestamp { get; init; } + + /// + /// Command bundle name. + /// + [MaxLength(250)] + [JsonPropertyName("commandbundle")] + public required string CommandBundle { get; init; } + + /// + /// Command extension name. + /// + [MaxLength(250)] + [JsonPropertyName("commandextension")] + public required string CommandExtension { get; init; } + + /// + /// Command name. + /// + [MaxLength(250)] + [JsonPropertyName("commandname")] + public required string CommandName { get; init; } + + /// + /// Command unique name. + /// + [MaxLength(500)] + [JsonPropertyName("commanduniquename")] + public required string CommandUniqueName { get; init; } + + /// + /// Document Title property. + /// + [MaxLength(250)] + [JsonPropertyName("docname")] + public string? DocumentName { get; init; } + + /// + /// Document PathName + /// property. + /// + [MaxLength(1024)] + [JsonPropertyName("docpath")] + public string? DocumentPath { get; init; } + + /// + /// Script executed result code. + ///
ResultCode + /// enumeration. + ///
+ [JsonPropertyName("resultcode")] + public int ResultCode { get; init; } + + /// + /// Executed script path. + /// + [MaxLength(1024)] + [JsonPropertyName("scriptpath")] + public required string ScriptPath { get; init; } + + /// + /// Information about execution. + /// + [JsonPropertyName("trace")] + public required TraceInfoDto Trace { get; init; } + + /// + /// Additional command results. + /// + [MaxLength(8000)] + [JsonPropertyName("commandresults")] + public string? CommandResults { get; init; } + } +} \ No newline at end of file diff --git a/src/Telemetry.Api/Application/DTOs/StatusRecordDto.cs b/src/Telemetry.Api/Application/DTOs/StatusRecordDto.cs new file mode 100644 index 0000000..43241a3 --- /dev/null +++ b/src/Telemetry.Api/Application/DTOs/StatusRecordDto.cs @@ -0,0 +1,52 @@ +using System.Text.Json.Serialization; + +namespace Telemetry.Api.Application.DTOs +{ + /// + /// Server status information. + /// + public class StatusRecordDto + { + /// + /// Connection status (pass or fail). + /// + [JsonPropertyName("status")] + public required string Status { get; init; } + + /// + /// Service unique id. + /// + [JsonPropertyName("serviceid")] + public required Guid ServiceId { get; init; } + + /// + /// Service version. + /// + [JsonPropertyName("version")] + public required string Version { get; init; } + + /// + /// Check information. + /// + [JsonPropertyName("checks")] + public required Dictionary Checks { get; init; } + } + + /// + /// Data transfer object representing the status check details. + /// + public class StatusCheckDto + { + /// + /// Data base connection status (pass or fail). + /// + [JsonPropertyName("status")] + public required string Status { get; init; } + + /// + /// Data base version. + /// + [JsonPropertyName("version")] + public required string Version { get; init; } + } +} \ No newline at end of file diff --git a/src/Telemetry.Api/Application/DTOs/TraceInfoDto.cs b/src/Telemetry.Api/Application/DTOs/TraceInfoDto.cs new file mode 100644 index 0000000..32fa4cd --- /dev/null +++ b/src/Telemetry.Api/Application/DTOs/TraceInfoDto.cs @@ -0,0 +1,25 @@ +using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; + +namespace Telemetry.Api.Application.DTOs +{ + /// + /// Script executed information. + /// + public class TraceInfoDto + { + /// + /// Script executed + /// message. + /// + [MaxLength(8000)] + [JsonPropertyName("message")] + public required string Message { get; init; } + + /// + /// Script engine information. + /// + [JsonPropertyName("engine")] + public required EngineInfoDto Engine { get; init; } + } +} \ No newline at end of file diff --git a/src/Telemetry.Api/Application/Interfaces/IApplicationDbContext.cs b/src/Telemetry.Api/Application/Interfaces/IApplicationDbContext.cs new file mode 100644 index 0000000..96bc143 --- /dev/null +++ b/src/Telemetry.Api/Application/Interfaces/IApplicationDbContext.cs @@ -0,0 +1,63 @@ +using Microsoft.EntityFrameworkCore; +using Telemetry.Api.Domain.Models; + +namespace Telemetry.Api.Application.Interfaces +{ + /// + /// Represents the contract for the application's database context. + /// Defines the operations and entities available for data access in the application. + /// + public interface IApplicationDbContext + { + /// + /// Represents a collection of event records associated with an entity or process. + /// This property is used to store and manage information about specific occurrences + /// or actions that are relevant to the application context. + /// + /// + /// Event records stored in this property can include details such as timestamps, + /// descriptions, identifiers, and metadata. It is typically used for logging, + /// auditing, or tracking purposes. + /// + DbSet EventRecords { get; } + + /// + /// Stores a collection of script records associated with the application or system context. + /// This property is utilized to manage and organize information related to scripts, + /// their configurations, or execution details. + /// + /// + /// Script records contained in this property may include data such as script names, + /// execution statuses, parameters, or any related metadata. It is commonly used + /// for monitoring, debugging, or storing script-related information in a structured manner. + /// + DbSet ScriptRecords { get; } + + /// + /// Asynchronously saves all changes made in the current context to the database. + /// + /// A task that represents the asynchronous save operation. + /// The task result contains the number of state entries written to the database. + Task SaveChangesAsync(CancellationToken cancellationToken); + + /// + /// Asynchronously checks if a connection to the database can be established. + /// + /// A task that represents the asynchronous operation. + /// The task result contains a boolean value indicating whether the connection attempt succeeded. + Task CanConnectAsync(CancellationToken cancellationToken); + + /// + /// Retrieves the database provider being used by the application. + /// + /// A string representing the name of the database provider. + string GetDbProvider(); + + /// + /// Asynchronously retrieves the database version. + /// + /// A task that represents the asynchronous operation. + /// The task result contains the version string of the database. + Task GetDbVersionAsync(CancellationToken cancellationToken); + } +} \ No newline at end of file diff --git a/src/Telemetry.Api/Application/Interfaces/IServiceInfo.cs b/src/Telemetry.Api/Application/Interfaces/IServiceInfo.cs new file mode 100644 index 0000000..739d765 --- /dev/null +++ b/src/Telemetry.Api/Application/Interfaces/IServiceInfo.cs @@ -0,0 +1,20 @@ +namespace Telemetry.Api.Application.Interfaces +{ + /// + /// Represents a service information interface that provides details + /// or metadata about a specific service. + /// + public interface IServiceInfo + { + /// + /// Gets or sets the unique identifier for the service. + /// + /// + /// The ServiceId property is used to uniquely identify a specific service + /// within the system. This value is typically generated or assigned + /// during service creation and should remain constant to ensure + /// consistent identification. + /// + Guid ServiceId { get; } + } +} \ No newline at end of file diff --git a/src/Telemetry.Api/Application/Mappings/TelemetryMappingExtensions.cs b/src/Telemetry.Api/Application/Mappings/TelemetryMappingExtensions.cs new file mode 100644 index 0000000..7a8326f --- /dev/null +++ b/src/Telemetry.Api/Application/Mappings/TelemetryMappingExtensions.cs @@ -0,0 +1,213 @@ +using Telemetry.Api.Application.DTOs; +using Telemetry.Api.Domain.Models; + +namespace Telemetry.Api.Application.Mappings +{ + /// + /// Provides extension methods for mapping telemetry-related data. + /// + public static class TelemetryMappingExtensions + { + /// + /// Converts the specified source object to a model representation. + /// + /// The source object to be converted. + /// A new instance of the model object created from the source. + public static MetaRecord ToModel(this MetaDto dto) + { + return new MetaRecord {SchemaVersion = new Version(dto.SchemaVersion.Major, dto.SchemaVersion.Minor)}; + } + + /// + /// Converts the specified source object to a data transfer object (DTO). + /// + /// The source object to be converted. + /// A new instance of the data transfer object (DTO) created from the source. + public static MetaDto ToDto(this MetaRecord model) + { + return new MetaDto {SchemaVersion = new Version(model.SchemaVersion.Major, model.SchemaVersion.Minor)}; + } + + /// + /// Transforms the input data transfer object into its corresponding model representation. + /// + /// The input data transfer object to be transformed. + /// An instance of the model created from the provided data transfer object. + public static EngineInfo ToModel(this EngineInfoDto dto) + { + return new EngineInfo + { + Type = dto.Type, Version = dto.Version, SysPaths = dto.SysPath, Configs = dto.Configs + }; + } + + /// + /// Converts the specified source model into a Data Transfer Object (DTO) representation. + /// + /// The source model to be converted. + /// A new DTO instance created from the provided model. + public static EngineInfoDto ToDto(this EngineInfo model) + { + return new EngineInfoDto + { + Type = model.Type, Version = model.Version, SysPath = model.SysPaths, Configs = model.Configs + }; + } + + /// + /// Transforms the provided data transfer object (DTO) into its corresponding model representation. + /// + /// The data transfer object to be transformed. + /// A model instance derived from the given data transfer object. + public static TraceInfo ToModel(this TraceInfoDto dto) + { + return new TraceInfo {Message = dto.Message, Engine = dto.Engine.ToModel()}; + } + + /// + /// Converts the specified model object to a data transfer object (DTO) representation. + /// + /// The model object to be converted. + /// A new instance of the DTO created from the model. + public static TraceInfoDto ToDto(this TraceInfo model) + { + return new TraceInfoDto {Message = model.Message, Engine = model.Engine.ToDto()}; + } + + /// + /// Transforms the provided data transfer object into its corresponding model representation. + /// + /// The data transfer object to be transformed. + /// The model object derived from the given data transfer object. + public static ScriptRecord ToModel(this ScriptRecordDto dto) + { + return new ScriptRecord + { + Id = Guid.CreateVersion7(), + SessionId = dto.SessionId, + Meta = dto.Meta.ToModel(), + Timestamp = dto.Timestamp, + Username = dto.Username, + HostUsername = dto.HostUsername, + RevitBuild = dto.RevitBuild, + RevitVersion = dto.RevitVersion, + PyRevitVersion = dto.PyRevitVersion, + CloneName = dto.CloneName, + IsDebug = dto.IsDebug, + IsConfig = dto.IsConfig, + IsExecFromGui = dto.IsExecFromGui, + ExecId = dto.ExecId, + ExecTimestamp = dto.ExecTimestamp, + CommandBundle = dto.CommandBundle, + CommandExtension = dto.CommandExtension, + CommandName = dto.CommandName, + CommandUniqueName = dto.CommandUniqueName, + DocumentName = dto.DocumentName, + DocumentPath = dto.DocumentPath, + ResultCode = dto.ResultCode, + ScriptPath = dto.ScriptPath, + Trace = dto.Trace.ToModel(), + CommandResults = dto.CommandResults + }; + } + + /// + /// Converts the specified source object to a data transfer object representation. + /// + /// The source object to be converted. + /// A new instance of the data transfer object created from the source. + public static ScriptRecordDto ToDto(this ScriptRecord model) + { + return new ScriptRecordDto + { + SessionId = model.SessionId, + Meta = model.Meta.ToDto(), + Timestamp = model.Timestamp, + Username = model.Username, + HostUsername = model.HostUsername, + RevitBuild = model.RevitBuild, + RevitVersion = model.RevitVersion, + PyRevitVersion = model.PyRevitVersion, + CloneName = model.CloneName, + IsDebug = model.IsDebug, + IsConfig = model.IsConfig, + IsExecFromGui = model.IsExecFromGui, + ExecId = model.ExecId, + ExecTimestamp = model.ExecTimestamp, + CommandBundle = model.CommandBundle, + CommandExtension = model.CommandExtension, + CommandName = model.CommandName, + CommandUniqueName = model.CommandUniqueName, + DocumentName = model.DocumentName, + DocumentPath = model.DocumentPath, + ResultCode = model.ResultCode, + ScriptPath = model.ScriptPath, + Trace = model.Trace.ToDto(), + CommandResults = model.CommandResults + }; + } + + /// + /// Transforms the provided DTO into its corresponding model representation. + /// + /// The data transfer object to be transformed. + /// An instance of the model derived from the given DTO. + public static EventRecord ToModel(this EventRecordDto dto) + { + return new EventRecord + { + Id = Guid.CreateVersion7(), + HandlerId = dto.HandlerId, + Meta = dto.Meta.ToModel(), + EventType = dto.EventType, + Status = dto.Status, + Timestamp = dto.Timestamp, + Username = dto.Username, + HostUsername = dto.HostUsername, + RevitBuild = dto.RevitBuild, + RevitVersion = dto.RevitVersion, + Cancelled = dto.Cancelled, + Cancellable = dto.Cancellable, + DocumentId = dto.DocumentId, + DocumentType = dto.DocumentType, + DocumentTemplate = dto.DocumentTemplate, + DocumentName = dto.DocumentName, + DocumentPath = dto.DocumentPath, + ProjectName = dto.ProjectName, + ProjectNum = dto.ProjectNum, + EventArgs = dto.EventArgs + }; + } + + /// + /// Converts the specified model object to a data transfer object representation. + /// + /// The model object to be converted. + /// A new instance of the data transfer object created from the model. + public static EventRecordDto ToDto(this EventRecord model) + { + return new EventRecordDto + { + HandlerId = model.HandlerId, + Meta = model.Meta.ToDto(), + EventType = model.EventType, + Status = model.Status, + Timestamp = model.Timestamp, + Username = model.Username, + HostUsername = model.HostUsername, + RevitBuild = model.RevitBuild, + RevitVersion = model.RevitVersion, + Cancelled = model.Cancelled, + Cancellable = model.Cancellable, + DocumentId = model.DocumentId, + DocumentType = model.DocumentType, + DocumentTemplate = model.DocumentTemplate, + DocumentName = model.DocumentName, + DocumentPath = model.DocumentPath, + ProjectName = model.ProjectName, + ProjectNum = model.ProjectNum, + EventArgs = model.EventArgs + }; + } + } +} \ No newline at end of file diff --git a/src/Telemetry.Api/Application/Services/ServiceInfo.cs b/src/Telemetry.Api/Application/Services/ServiceInfo.cs new file mode 100644 index 0000000..87a2e33 --- /dev/null +++ b/src/Telemetry.Api/Application/Services/ServiceInfo.cs @@ -0,0 +1,29 @@ +using Telemetry.Api.Application.Interfaces; + +namespace Telemetry.Api.Application.Services +{ + /// + /// Represents information about a service, encapsulating details + /// such as the service name, description, status, and other relevant metadata. + /// + public class ServiceInfo : IServiceInfo + { + /// + /// Represents information about a service, including its name, + /// description, and any related metadata. + /// + public ServiceInfo() + { + ServiceId = Guid.NewGuid(); + } + + /// + /// Gets or sets the unique identifier for the service. + /// + /// + /// The ServiceId property is used to uniquely identify a specific service within the system. + /// This identifier is typically assigned automatically and is immutable once set. + /// + public Guid ServiceId { get; } + } +} \ No newline at end of file diff --git a/src/Telemetry.Api/Dockerfile b/src/Telemetry.Api/Dockerfile new file mode 100644 index 0000000..5542d6c --- /dev/null +++ b/src/Telemetry.Api/Dockerfile @@ -0,0 +1,53 @@ +FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS base + +# fix cannot load library libgssapi_krb5.so.2 (postgres) +RUN apt-get update \ + && apt-get install -y --no-install-recommends libgssapi-krb5-2 \ + && rm -rf /var/lib/apt/lists/* + +USER $APP_UID +WORKDIR /app + +EXPOSE 8080 + +FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build +ARG BUILD_CONFIGURATION=Release +WORKDIR /src + +COPY ["src/Telemetry.Api/Telemetry.Api.csproj", "Telemetry.Api/"] +COPY ["src/Telemetry.Migrations.Oracle/Telemetry.Migrations.Oracle.csproj", "Telemetry.Migrations.Oracle/"] +COPY ["src/Telemetry.Migrations.Postgres/Telemetry.Migrations.Postgres.csproj", "Telemetry.Migrations.Postgres/"] +COPY ["src/Telemetry.Migrations.Sqlite/Telemetry.Migrations.Sqlite.csproj", "Telemetry.Migrations.Sqlite/"] +COPY ["src/Telemetry.Migrations.SqlServer/Telemetry.Migrations.SqlServer.csproj", "Telemetry.Migrations.SqlServer/"] + +RUN dotnet restore "./Telemetry.Api/Telemetry.Api.csproj" +RUN dotnet restore "./Telemetry.Migrations.Oracle/Telemetry.Migrations.Oracle.csproj" +RUN dotnet restore "./Telemetry.Migrations.Postgres/Telemetry.Migrations.Postgres.csproj" +RUN dotnet restore "./Telemetry.Migrations.Sqlite/Telemetry.Migrations.Sqlite.csproj" +RUN dotnet restore "./Telemetry.Migrations.SqlServer/Telemetry.Migrations.SqlServer.csproj" + +COPY . . +RUN dotnet build "./src/Telemetry.Api/Telemetry.Api.csproj" -c $BUILD_CONFIGURATION -o /app/build +RUN dotnet build "./src/Telemetry.Migrations.Oracle/Telemetry.Migrations.Oracle.csproj" -c $BUILD_CONFIGURATION -o /app/build +RUN dotnet build "./src/Telemetry.Migrations.Postgres/Telemetry.Migrations.Postgres.csproj" -c $BUILD_CONFIGURATION -o /app/build +RUN dotnet build "./src/Telemetry.Migrations.Sqlite/Telemetry.Migrations.Sqlite.csproj" -c $BUILD_CONFIGURATION -o /app/build +RUN dotnet build "./src/Telemetry.Migrations.SqlServer/Telemetry.Migrations.SqlServer.csproj" -c $BUILD_CONFIGURATION -o /app/build + +FROM build AS publish +ARG BUILD_CONFIGURATION=Release +RUN dotnet publish "./src/Telemetry.Api/Telemetry.Api.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false +RUN dotnet publish "./src/Telemetry.Migrations.Oracle/Telemetry.Migrations.Oracle.csproj" -c $BUILD_CONFIGURATION -o /app/migrations/oracle +RUN dotnet publish "./src/Telemetry.Migrations.Postgres/Telemetry.Migrations.Postgres.csproj" -c $BUILD_CONFIGURATION -o /app/migrations/postgres +RUN dotnet publish "./src/Telemetry.Migrations.Sqlite/Telemetry.Migrations.Sqlite.csproj" -c $BUILD_CONFIGURATION -o /app/migrations/sqlite +RUN dotnet publish "./src/Telemetry.Migrations.SqlServer/Telemetry.Migrations.SqlServer.csproj" -c $BUILD_CONFIGURATION -o /app/migrations/sqlserver + +FROM base AS final +WORKDIR /app + +COPY --from=publish /app/publish . +COPY --from=publish /app/migrations/oracle/Telemetry.Migrations.Oracle.dll . +COPY --from=publish /app/migrations/postgres/Telemetry.Migrations.Postgres.dll . +COPY --from=publish /app/migrations/sqlite/Telemetry.Migrations.Sqlite.dll . +COPY --from=publish /app/migrations/sqlserver/Telemetry.Migrations.SqlServer.dll . + +ENTRYPOINT ["dotnet", "Telemetry.Api.dll"] diff --git a/src/Telemetry.Api/Domain/Models/EngineInfo.cs b/src/Telemetry.Api/Domain/Models/EngineInfo.cs new file mode 100644 index 0000000..e1512af --- /dev/null +++ b/src/Telemetry.Api/Domain/Models/EngineInfo.cs @@ -0,0 +1,40 @@ +using MongoDB.Bson.Serialization.Attributes; +using System.ComponentModel.DataAnnotations; + +namespace Telemetry.Api.Domain.Models +{ + /// + /// Script engine information. + /// + public class EngineInfo + { + /// + /// Engine type name. + ///
Engine types. + ///
+ [MaxLength(100)] + [BsonElement("type")] + public required string Type { get; init; } + + /// + /// Engine version. + ///
Engines list. + ///
+ [MaxLength(100)] + [BsonElement("version")] + public required string Version { get; init; } + + /// + /// System paths using by script. + /// + [BsonElement("syspath")] + public string[]? SysPaths { get; init; } + + /// + /// Dynamic script configs data. + /// + [MaxLength(8000)] + [BsonElement("configs")] + public string? Configs { get; init; } + } +} \ No newline at end of file diff --git a/src/Telemetry.Api/Domain/Models/EventRecord.cs b/src/Telemetry.Api/Domain/Models/EventRecord.cs new file mode 100644 index 0000000..227c685 --- /dev/null +++ b/src/Telemetry.Api/Domain/Models/EventRecord.cs @@ -0,0 +1,173 @@ +using MongoDB.Bson; +using MongoDB.Bson.Serialization.Attributes; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; + +namespace Telemetry.Api.Domain.Models +{ + /// + /// Event record information. + /// + [Table("events")] + public class EventRecord + { + /// + /// Event id. + /// + public Guid Id { get; init; } + + /// + /// Unique event id. + /// + [BsonElement("handler_id")] + public Guid HandlerId { get; init; } + + /// + /// Information about telemetry record. + /// + [BsonElement("meta")] + public required MetaRecord Meta { get; init; } + + /// + /// Event type name. + /// + [MaxLength(100)] + [BsonElement("type")] + public required string EventType { get; init; } + + /// + /// Revit event + /// status. + /// + [MaxLength(100)] + [BsonElement("status")] + public string? Status { get; init; } + + /// + /// When event started. + /// + [BsonElement("timestamp")] + [BsonRepresentation(BsonType.DateTime)] + public DateTimeOffset Timestamp { get; init; } + + /// + /// Username + /// who use Autodesk Revit (sets in options). + /// + [MaxLength(100)] + [BsonElement("username")] + public required string Username { get; init; } + + /// + /// Username + /// who logged in Windows. + /// + [MaxLength(100)] + [BsonElement("host_user")] + public string? HostUsername { get; init; } + + /// + /// Internal + /// build number + /// of the Autodesk Revit application. + /// + [MaxLength(100)] + [BsonElement("revitbuild")] + public required string RevitBuild { get; init; } + + /// + /// Return the + /// primary version + /// of the Revit application. + /// + [MaxLength(100)] + [BsonElement("revit")] + public required string RevitVersion { get; init; } + + /// + /// If event was cancelled , otherwise . + ///
RevitAPIEventArgs + /// IsCancelled method. + ///
+ [BsonElement("cancelled")] + public bool? Cancelled { get; init; } + + /// + /// If event can cancel , otherwise . + ///
RevitAPIEventArgs + /// Cancellable property. + ///
+ [BsonElement("cancellable")] + public bool? Cancellable { get; init; } + + /// + /// Id of the document that has just been closed. + ///
DocumentClosingEventArgs + /// DocumentId property. + ///
DocumentClosedEventArgs + /// DocumentId property. + ///
+ [BsonElement("docid")] + public int DocumentId { get; init; } + + /// + /// Type of the document, e.g. Project or Template. + ///
DocumentType + /// enumeration. + ///
DocumentOpeningEventArgs + /// DocumentType property. + ///
DocumentCreatingEventArgs + /// DocumentType property. + ///
+ [MaxLength(100)] + [BsonElement("doctype")] + public string? DocumentType { get; init; } + + /// + /// Document template name. + ///
DocumentCreatingEventArgs + /// Template property. + ///
+ [MaxLength(100)] + [BsonElement("doctemplate")] + public string? DocumentTemplate { get; init; } + + /// + /// Document Title property. + /// + [MaxLength(250)] + [BsonElement("docname")] + public string? DocumentName { get; init; } + + /// + /// Document PathName + /// property. + /// + [MaxLength(1024)] + [BsonElement("docpath")] + public string? DocumentPath { get; init; } + + /// + /// Project name + /// (BuiltInParameter.PROJECT_NAME). + /// + [MaxLength(250)] + [BsonElement("projectname")] + public string? ProjectName { get; init; } + + /// + /// Project number + /// (BuiltInParameter.PROJECT_NUMBER). + /// + [MaxLength(100)] + [BsonElement("projectnum")] + public string? ProjectNum { get; init; } + + /// + /// Dynamic event args data. + /// + [MaxLength(8000)] + [BsonElement("args")] + public string? EventArgs { get; init; } + } +} \ No newline at end of file diff --git a/src/Telemetry.Api/Domain/Models/MetaRecord.cs b/src/Telemetry.Api/Domain/Models/MetaRecord.cs new file mode 100644 index 0000000..9428dc2 --- /dev/null +++ b/src/Telemetry.Api/Domain/Models/MetaRecord.cs @@ -0,0 +1,16 @@ +using MongoDB.Bson.Serialization.Attributes; + +namespace Telemetry.Api.Domain.Models +{ + /// + /// Record metadata. + /// + public class MetaRecord + { + /// + /// Schema version. + /// + [BsonElement("schema")] + public required Version SchemaVersion { get; init; } + } +} \ No newline at end of file diff --git a/src/Telemetry.Api/Domain/Models/ScriptRecord.cs b/src/Telemetry.Api/Domain/Models/ScriptRecord.cs new file mode 100644 index 0000000..c49ca07 --- /dev/null +++ b/src/Telemetry.Api/Domain/Models/ScriptRecord.cs @@ -0,0 +1,196 @@ +using MongoDB.Bson; +using MongoDB.Bson.Serialization.Attributes; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; + +namespace Telemetry.Api.Domain.Models +{ + /// + /// Script record information. + /// + [Table("scripts")] + public class ScriptRecord + { + /// + /// Scripts id. + /// + public Guid Id { get; init; } + + /// + /// Unique session id (created when revit is opened). + /// + [BsonElement("sessionid")] + public Guid SessionId { get; init; } + + /// + /// Information about telemetry record. + /// + [BsonElement("meta")] + public required MetaRecord Meta { get; init; } + + /// + /// When script started. + /// + [BsonElement("timestamp")] + [BsonRepresentation(BsonType.DateTime)] + public DateTimeOffset Timestamp { get; init; } + + /// + /// Username + /// who use Autodesk Revit (sets in options). + /// + [MaxLength(100)] + [BsonElement("username")] + public required string Username { get; init; } + + /// + /// Username + /// who logged in Windows. + /// + [MaxLength(100)] + [BsonElement("host_user")] + public string? HostUsername { get; init; } + + /// + /// Internal + /// build number + /// of the Autodesk Revit application. + /// + [MaxLength(100)] + [BsonElement("revitbuild")] + public required string RevitBuild { get; init; } + + /// + /// Return the + /// primary version + /// of the Revit application. + /// + [MaxLength(100)] + [BsonElement("revit")] + public required string RevitVersion { get; init; } + + /// + /// pyrevit build version. + /// + [MaxLength(100)] + [BsonElement("pyrevit")] + public required string PyRevitVersion { get; init; } + + /// + /// pyrevit + /// clone name. + /// + [MaxLength(100)] + [BsonElement("clone")] + public required string CloneName { get; init; } + + /// + /// pyrevit + /// + /// debug + /// mode + /// . + /// + [BsonElement("debug")] + public bool IsDebug { get; init; } + + /// + /// pyrevit + /// config mode. + /// + [BsonElement("config")] + public bool IsConfig { get; init; } + + /// + /// If script was run from GUI (Click Revit Ribbon) , otherwise . + /// + [BsonElement("from_gui")] + public bool IsExecFromGui { get; init; } + + /// + /// Unique execution id. + /// + [MaxLength(100)] + [BsonElement("exec_id")] + public required string ExecId { get; init; } + + /// + /// When script executed. + /// + [BsonElement("exec_timestamp")] + [BsonRepresentation(BsonType.DateTime)] + public DateTimeOffset ExecTimestamp { get; init; } + + /// + /// Command bundle name. + /// + [MaxLength(250)] + [BsonElement("commandbundle")] + public required string CommandBundle { get; init; } + + /// + /// Command extension name. + /// + [MaxLength(250)] + [BsonElement("commandextension")] + public required string CommandExtension { get; init; } + + /// + /// Command name. + /// + [MaxLength(250)] + [BsonElement("commandname")] + public required string CommandName { get; init; } + + /// + /// Command unique name. + /// + [MaxLength(500)] + [BsonElement("commanduniquename")] + public required string CommandUniqueName { get; init; } + + /// + /// Document Title property. + /// + [MaxLength(250)] + [BsonElement("docname")] + public string? DocumentName { get; init; } + + /// + /// Document PathName + /// property. + /// + [MaxLength(1024)] + [BsonElement("docpath")] + public string? DocumentPath { get; init; } + + /// + /// Script executed result code. + ///
ResultCode + /// enumeration. + ///
+ [BsonElement("resultcode")] + public int ResultCode { get; init; } + + /// + /// Executed script path. + /// + [MaxLength(1024)] + [BsonElement("scriptpath")] + public required string ScriptPath { get; init; } + + /// + /// Information about execution. + /// + [BsonElement("trace")] + public required TraceInfo Trace { get; init; } + + /// + /// Additional command results. + /// + [MaxLength(8000)] + [BsonElement("commandresults")] + public string? CommandResults { get; init; } + } +} \ No newline at end of file diff --git a/src/Telemetry.Api/Domain/Models/TraceInfo.cs b/src/Telemetry.Api/Domain/Models/TraceInfo.cs new file mode 100644 index 0000000..3a852bd --- /dev/null +++ b/src/Telemetry.Api/Domain/Models/TraceInfo.cs @@ -0,0 +1,25 @@ +using MongoDB.Bson.Serialization.Attributes; +using System.ComponentModel.DataAnnotations; + +namespace Telemetry.Api.Domain.Models +{ + /// + /// Script executed information. + /// + public class TraceInfo + { + /// + /// Script executed + /// message. + /// + [MaxLength(8000)] + [BsonElement("message")] + public required string Message { get; init; } + + /// + /// Script engine information. + /// + [BsonElement("engine")] + public required EngineInfo Engine { get; init; } + } +} \ No newline at end of file diff --git a/src/Telemetry.Api/Infrastructure/Persistence/ApplicationDbContext.cs b/src/Telemetry.Api/Infrastructure/Persistence/ApplicationDbContext.cs new file mode 100644 index 0000000..9183320 --- /dev/null +++ b/src/Telemetry.Api/Infrastructure/Persistence/ApplicationDbContext.cs @@ -0,0 +1,210 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.ChangeTracking; +using System.Data; +using System.Data.Common; +using System.Text.Json; +using Telemetry.Api.Application.Interfaces; +using Telemetry.Api.Domain.Models; + +namespace Telemetry.Api.Infrastructure.Persistence +{ + /// + /// Represents the database context for the application, providing access to the database + /// and handling the interactions between the application and the data storage. + /// + /// + /// This class is typically used with Entity Framework Core to define the database schema + /// through DbSet properties and manage entity persistence. + /// It encapsulates the data connection and performs CRUD operations on the underlying database. + /// + /// + /// The ApplicationDbContext class should be instantiated and managed using dependency + /// injection within the application's service container. Configure the DbContext options + /// in the application startup or configuration class. + /// + public class ApplicationDbContext : DbContext, IApplicationDbContext + { + /// + /// Represents the database context for the application. + /// Provides access to the database tables and enables CRUD operations. + /// Extends from DbContext to leverage EF Core functionality for managing database interactions. + /// + public ApplicationDbContext(DbContextOptions options) : base(options) { } + + /// + /// Gets or sets the collection of event records associated with the current context. + /// + /// + /// This property holds a list of event data used for logging, auditing, or tracking purposes. + /// It can be used to store and retrieve information about events in a structured format. + /// + public DbSet EventRecords => Set(); + + /// + /// Gets or sets the collection of script records associated with the current context. + /// + /// + /// This property contains a list of script data, which can be used for processing, + /// execution tracking, or storing metadata related to scripts. + /// + public DbSet ScriptRecords => Set(); + + /// + /// Asynchronously checks whether a successful connection to the database can be established. + /// This method verifies connectivity without performing any data manipulation or transactions. + /// + /// + /// A task that represents the asynchronous operation. The task result contains a boolean value indicating + /// whether the connection to the database was successful (true) or unsuccessful (false). + /// + public Task CanConnectAsync(CancellationToken cancellationToken) + { + return Database.CanConnectAsync(cancellationToken); + } + + /// + /// Retrieves the database provider being used for the application's data access. + /// This method determines and returns the current database provider implementation. + /// + /// The database provider instance configured for the application. + public string GetDbProvider() + { + return Database.ProviderName ?? "unknown"; + } + + /// + /// Asynchronously retrieves the current version of the database. + /// Useful for determining database schema versions or migrations required. + /// + /// A token to monitor for cancellation requests. + /// A task representing the asynchronous operation. The task result contains the database version as a string. + public async Task GetDbVersionAsync(CancellationToken cancellationToken) + { + try + { + string? query = null; + if (Database.IsNpgsql()) + { + query = "SELECT version()"; + } + else if (Database.IsOracle()) + { + query = "SELECT * FROM v$version;"; + } + else if (Database.IsSqlServer()) + { + query = "SELECT @@VERSION"; + } + else if (Database.IsSqlite()) + { + query = "SELECT sqlite_version()"; + } + else if (Database.IsInMemory()) + { + return "memorydb"; + } + + if (query != null) + { + await using DbCommand command = Database.GetDbConnection().CreateCommand(); + + command.CommandText = query; + if (command.Connection!.State != ConnectionState.Open) + { + await command.Connection.OpenAsync(cancellationToken); + } + + object? result = await command.ExecuteScalarAsync(cancellationToken); + return result?.ToString() ?? "unknown"; + } + } + catch + { + // ignored + } + + return "unknown"; + } + + /// + /// Configures the model relationships, constraints, and schema definitions for the database context. + /// Called when the database model is being created or initialized. + /// + /// The builder used to define the model structure and relationships. + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder.Entity(entity => + { + entity.ToTable("script_record"); + entity.HasKey(e => e.Id); + entity.Property(e => e.Id).HasColumnName("id"); + entity.Property(e => e.SessionId).HasColumnName("sessionid"); + entity.Property(e => e.Timestamp).HasColumnName("timestamp"); + entity.Property(e => e.Username).HasColumnName("username"); + entity.Property(e => e.HostUsername).HasColumnName("host_user"); + entity.Property(e => e.RevitBuild).HasColumnName("revitbuild"); + entity.Property(e => e.RevitVersion).HasColumnName("revit"); + entity.Property(e => e.PyRevitVersion).HasColumnName("pyrevit"); + entity.Property(e => e.CloneName).HasColumnName("clone"); + entity.Property(e => e.IsDebug).HasColumnName("debug"); + entity.Property(e => e.IsConfig).HasColumnName("config"); + entity.Property(e => e.IsExecFromGui).HasColumnName("from_gui"); + entity.Property(e => e.ExecId).HasColumnName("exec_id"); + entity.Property(e => e.ExecTimestamp).HasColumnName("exec_timestamp"); + entity.Property(e => e.CommandBundle).HasColumnName("commandbundle"); + entity.Property(e => e.CommandExtension).HasColumnName("commandextension"); + entity.Property(e => e.CommandName).HasColumnName("commandname"); + entity.Property(e => e.CommandUniqueName).HasColumnName("commanduniquename"); + entity.Property(e => e.DocumentName).HasColumnName("docname"); + entity.Property(e => e.DocumentPath).HasColumnName("docpath"); + entity.Property(e => e.ResultCode).HasColumnName("resultcode"); + entity.Property(e => e.ScriptPath).HasColumnName("scriptpath"); + entity.Property(e => e.CommandResults).HasColumnName("commandresults"); + + entity.Property(e => e.Meta) + .HasColumnName("meta") + .HasConversion( + v => JsonSerializer.Serialize(v, (JsonSerializerOptions?)null), + v => JsonSerializer.Deserialize(v, (JsonSerializerOptions?)null)!); + + entity.Property(e => e.Trace) + .HasColumnName("trace") + .HasConversion( + v => JsonSerializer.Serialize(v, (JsonSerializerOptions?)null), + v => JsonSerializer.Deserialize(v, (JsonSerializerOptions?)null)!); + }); + + modelBuilder.Entity(entity => + { + entity.ToTable("event_record"); + entity.HasKey(e => e.Id); + entity.Property(e => e.Id).HasColumnName("id"); + entity.Property(e => e.HandlerId).HasColumnName("handler_id"); + entity.Property(e => e.EventType).HasColumnName("type"); + entity.Property(e => e.Status).HasColumnName("status"); + entity.Property(e => e.Timestamp).HasColumnName("timestamp"); + entity.Property(e => e.Username).HasColumnName("username"); + entity.Property(e => e.HostUsername).HasColumnName("host_user"); + entity.Property(e => e.RevitBuild).HasColumnName("revitbuild"); + entity.Property(e => e.RevitVersion).HasColumnName("revit"); + entity.Property(e => e.Cancelled).HasColumnName("cancelled"); + entity.Property(e => e.DocumentId).HasColumnName("docid"); + entity.Property(e => e.DocumentType).HasColumnName("doctype"); + entity.Property(e => e.DocumentTemplate).HasColumnName("doctemplate"); + entity.Property(e => e.DocumentName).HasColumnName("docname"); + entity.Property(e => e.DocumentPath).HasColumnName("docpath"); + entity.Property(e => e.ProjectName).HasColumnName("projectname"); + entity.Property(e => e.ProjectNum).HasColumnName("projectnum"); + entity.Property(e => e.EventArgs).HasColumnName("args"); + + entity.Property(e => e.Meta) + .HasColumnName("meta") + .HasConversion( + v => JsonSerializer.Serialize(v, (JsonSerializerOptions?)null), + v => JsonSerializer.Deserialize(v, (JsonSerializerOptions?)null)!); + }); + + base.OnModelCreating(modelBuilder); + } + } +} \ No newline at end of file diff --git a/src/Telemetry.Api/JsonConverters/DynamicDataBsonSerializer.cs b/src/Telemetry.Api/JsonConverters/DynamicDataBsonSerializer.cs new file mode 100644 index 0000000..0bd3c83 --- /dev/null +++ b/src/Telemetry.Api/JsonConverters/DynamicDataBsonSerializer.cs @@ -0,0 +1,25 @@ +using MongoDB.Bson; +using MongoDB.Bson.Serialization; +using MongoDB.Bson.Serialization.Serializers; + +namespace Telemetry.Api.JsonConverters; + +internal class DynamicDataBsonSerializer : SerializerBase +{ + public override string? Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) + { + return BsonDocumentSerializer.Instance.Deserialize(context).ToString(); + } + + public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, string? value) + { + if (string.IsNullOrEmpty(value)) + { + context.Writer.WriteNull(); + } + else + { + BsonDocumentSerializer.Instance.Serialize(context, BsonDocument.Parse(value)); + } + } +} \ No newline at end of file diff --git a/src/Telemetry.Api/JsonConverters/DynamicDataJsonConverter.cs b/src/Telemetry.Api/JsonConverters/DynamicDataJsonConverter.cs new file mode 100644 index 0000000..50515a4 --- /dev/null +++ b/src/Telemetry.Api/JsonConverters/DynamicDataJsonConverter.cs @@ -0,0 +1,22 @@ +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Telemetry.Api.JsonConverters; + +internal class DynamicDataJsonConverter : JsonConverter +{ + public override string? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + if (reader.TokenType == JsonTokenType.Null) + { + return null; + } + + return JsonDocument.ParseValue(ref reader).RootElement.GetRawText(); + } + + public override void Write(Utf8JsonWriter writer, string? value, JsonSerializerOptions options) + { + writer.WriteStringValue(value); + } +} \ No newline at end of file diff --git a/src/Telemetry.Api/Program.cs b/src/Telemetry.Api/Program.cs new file mode 100644 index 0000000..f51fdc4 --- /dev/null +++ b/src/Telemetry.Api/Program.cs @@ -0,0 +1,186 @@ +using Microsoft.AspNetCore.HttpLogging; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.OpenApi; +using Prometheus; +using Telemetry.Api.Application.Interfaces; +using Telemetry.Api.Application.Services; +using Telemetry.Api.Infrastructure.Persistence; +using Telemetry.Api.Web.Middleware; +using Serilog; +using System.Reflection; +using System.Runtime.Loader; + +WebApplicationBuilder builder = WebApplication.CreateBuilder(args); + +Log.Logger = new LoggerConfiguration() + .ReadFrom.Configuration(builder.Configuration) + .Enrich.FromLogContext() + .WriteTo.Console() + .CreateLogger(); + +builder.Host.UseSerilog(Log.Logger); + +builder.Services.AddHttpLogging(logging => +{ + logging.LoggingFields = HttpLoggingFields.All; + logging.RequestBodyLogLimit = 4096; + logging.ResponseBodyLogLimit = 4096; +}); + +builder.Services.AddDbContext(options => +{ + string? connectionString = builder.Configuration.GetConnectionString("DefaultConnection"); + string? dbProvider = builder.Configuration.GetValue("DbProvider")?.ToLower(); + + if (string.IsNullOrEmpty(connectionString)) + { + throw new InvalidOperationException("Missing connection string"); + } + + switch (dbProvider) + { + case "oracle": + Log.Information("Using Oracle database"); + options.UseOracle(connectionString, + x => x.MigrationsAssembly("Telemetry.Migrations.Oracle")); + + Log.Information("Load Oracle migration assembly"); + AssemblyLoadContext.Default.LoadFromAssemblyPath( + Path.Combine(Environment.CurrentDirectory, "Telemetry.Migrations.Oracle.dll")); + break; + case "postgres": + Log.Information("Using PostgresSQL database"); + options.UseNpgsql(connectionString, + x => x.MigrationsAssembly("Telemetry.Migrations.Postgres")); + + Log.Information("Load PostgresSQL migration assembly"); + AssemblyLoadContext.Default.LoadFromAssemblyPath( + Path.Combine(Environment.CurrentDirectory, "Telemetry.Migrations.Postgres.dll")); + break; + case "sqlite": + Log.Information("Using SQLite database"); + options.UseSqlite(connectionString, + x => x.MigrationsAssembly("Telemetry.Migrations.Sqlite")); + + Log.Information("Load SQLite migration assembly"); + AssemblyLoadContext.Default.LoadFromAssemblyPath( + Path.Combine(Environment.CurrentDirectory, "Telemetry.Migrations.Sqlite.dll")); + break; + case "mssql": + Log.Information("Using MS SQL database"); + options.UseSqlServer(connectionString, + x => x.MigrationsAssembly("Telemetry.Migrations.SqlServer")); + + Log.Information("Load MS SQL migration assembly"); + AssemblyLoadContext.Default.LoadFromAssemblyPath( + Path.Combine(Environment.CurrentDirectory, "Telemetry.Migrations.SqlServer.dll")); + break; + case "mongodb": + string mongoDbName = builder.Configuration.GetValue("MongoDbDatabaseName") ?? "telemetry"; + options.UseMongoDB(connectionString, mongoDbName); + Log.Information("Using MongoDB database"); + break; + default: + options.UseInMemoryDatabase("TelemetryDb"); + Log.Information("Using In a Memory database"); + break; + } +}); + +builder.Services.AddScoped(provider => provider.GetRequiredService()); +builder.Services.AddSingleton(); + +builder.Services.AddControllers(); + +builder.Services.AddEndpointsApiExplorer(); +builder.Services.AddSwaggerGen(options => +{ + string basePath = AppContext.BaseDirectory; + options.IncludeXmlComments(Path.Combine(basePath, "Telemetry.Api.xml")); + + options.SwaggerDoc("v2", + new OpenApiInfo + { + Version = "v2", + Title = "pyRevit Telemetry API", + Summary = "API for collecting platform usage telemetry and Revit application events from pyRevit.", + Description = + "This API provides endpoints for collecting, storing, and accessing telemetry data related to pyRevit platform usage, including user activity, command execution, performance metrics, and events raised inside the Autodesk Revit application. It is intended for monitoring usage patterns, analyzing user interactions, diagnosing issues, and auditing application behavior.", + Contact = new OpenApiContact {Name = "pyrevitlabs", Url = new Uri("https://www.pyrevitlabs.io/")}, + License = new OpenApiLicense + { + Name = "GNU GPL v3", + Url = new Uri( + "https://raw.githubusercontent.com/pyrevitlabs/telemetry-server/refs/heads/main/LICENSE.md") + } + }); +}); + +builder.Services.AddApiVersioning(options => +{ + options.AssumeDefaultVersionWhenUnspecified = true; + options.DefaultApiVersion = new ApiVersion(2, 0); + options.ReportApiVersions = true; +}); + +builder.Services.AddVersionedApiExplorer(setup => { + setup.GroupNameFormat = "'v'VVV"; + setup.SubstituteApiVersionInUrl = true; +}); + +WebApplication app = builder.Build(); + +app.UseMiddleware(); + +if (app.Environment.IsDevelopment()) +{ + app.MapOpenApi(); + app.UseSwagger(); + app.UseSwaggerUI(c => + { + c.SwaggerEndpoint("/swagger/v2/swagger.json", "pyRevit Telemetry API v2"); + }); + app.UseDeveloperExceptionPage(); +} + +app.UseRouting(); +app.UseHttpMetrics(); + +app.MapControllers(); +app.MapMetrics(); + +try +{ + Log.Information("Starting migration"); + + using IServiceScope scope = app.Services.CreateScope(); + ApplicationDbContext db = scope.ServiceProvider.GetRequiredService(); + + string? dbProvider = builder.Configuration.GetValue("DbProvider")?.ToLower(); + if (dbProvider is not "mongodb") + { + await db.Database.MigrateAsync(); + } + + Log.Information("Migration completed"); +} +catch (Exception ex) +{ + Log.Fatal(ex, "Migration terminated unexpectedly"); + throw; +} +finally +{ + Log.CloseAndFlush(); +} + +try +{ + app.Logger.LogInformation("Starting web host"); + await app.RunAsync(); +} +catch (Exception ex) +{ + app.Logger.LogCritical(ex, "Host terminated unexpectedly"); +} \ No newline at end of file diff --git a/src/Telemetry.Api/Properties/launchSettings.json b/src/Telemetry.Api/Properties/launchSettings.json new file mode 100644 index 0000000..a623894 --- /dev/null +++ b/src/Telemetry.Api/Properties/launchSettings.json @@ -0,0 +1,23 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": false, + "applicationUrl": "http://localhost:5030", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": false, + "applicationUrl": "https://localhost:7191;http://localhost:5030", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/src/Telemetry.Api/Telemetry.Api.csproj b/src/Telemetry.Api/Telemetry.Api.csproj new file mode 100644 index 0000000..402bded --- /dev/null +++ b/src/Telemetry.Api/Telemetry.Api.csproj @@ -0,0 +1,50 @@ + + + + net10.0 + enable + enable + Linux + true + + + + + + + + + + + + + + + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + + + + + + + + + + + + diff --git a/src/Telemetry.Api/Telemetry.Api.http b/src/Telemetry.Api/Telemetry.Api.http new file mode 100644 index 0000000..14971eb --- /dev/null +++ b/src/Telemetry.Api/Telemetry.Api.http @@ -0,0 +1,74 @@ +@Telemetry_Api_HostAddress = http://localhost:8080 + +### Get Status +GET {{Telemetry_Api_HostAddress}}/api/v2/status +Accept: application/json + +### Post Script Record +POST {{Telemetry_Api_HostAddress}}/api/v2/scripts +Content-Type: application/json + +{ + "sessionId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", + "meta": { + "schema": "2.0.0" + }, + "timestamp": "2024-03-27T10:00:00Z", + "username": "testuser", + "host_user": "ad\\testuser", + "revitBuild": "2024.1", + "revit": "Revit 2024", + "pyrevit": "4.8.12", + "clone": "master", + "debug": false, + "config": true, + "from_gui": true, + "exec_id": "exec-123", + "exec_timestamp": "2024-03-27T10:00:05Z", + "commandbundle": "bundle-xyz", + "commandextension": "ext-abc", + "commandname": "TestCommand", + "commanduniquename": "TestUniqueName", + "scriptpath": "C:/scripts/test.py", + "trace": { + "message": "Script executed successfully", + "engine": { + "type": "IronPython", + "version": "2.7.12", + "sysPath": [ + "path1", + "path2" + ], + "configs": "test configs" + } + } +} + +### Post Event Record +POST {{Telemetry_Api_HostAddress}}/api/v2/events +Content-Type: application/json + +{ + "handler_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", + "meta": { + "schema": "2.0.0" + }, + "type": "AppStartup", + "status": "success", + "timestamp": "2024-03-27T10:00:00Z", + "username": "testuser", + "host_user": "ad\\testuser", + "revitbuild": "2024.1", + "revit": "Revit 2024", + "cancelled": false, + "docid": 42, + "doctype": "doc type", + "doctemplate": "doc template", + "docname": "doc name", + "docpath": "C:\\doc.rvt", + "projectname": "doc.rvt", + "projectnum": "projectnum" +} + +### Get Prometheus Metrics +GET {{Telemetry_Api_HostAddress}}/metrics diff --git a/src/Telemetry.Api/Web/Controllers/TelemetryController.cs b/src/Telemetry.Api/Web/Controllers/TelemetryController.cs new file mode 100644 index 0000000..ccbce6a --- /dev/null +++ b/src/Telemetry.Api/Web/Controllers/TelemetryController.cs @@ -0,0 +1,144 @@ +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Telemetry.Api.Application.Mappings; +using Telemetry.Api.Application.DTOs; +using Telemetry.Api.Application.Interfaces; +using Telemetry.Api.Domain.Models; + +namespace Telemetry.Api.Web.Controllers +{ + /// + /// Controller + /// + [ApiController] + [ApiVersion("2")] + [Route("api/v{version:apiVersion}")] + public class TelemetryController : ControllerBase + { + private readonly IApplicationDbContext _context; + private readonly ILogger _logger; + private readonly IServiceInfo _serviceInfo; + + /// + /// Creates controller. + /// + /// Context. + /// Logger. + /// Service info. + public TelemetryController(IApplicationDbContext context, ILogger logger, + IServiceInfo serviceInfo) + { + _context = context; + _logger = logger; + _serviceInfo = serviceInfo; + } + + /// + /// Adds script record to DB. + /// + /// Adding script records. + /// Returns adding script records task. + [HttpPost("scripts")] + [ProducesResponseType(200)] + [ProducesResponseType(500)] + [ProducesResponseType(503)] + public async Task PostScript([FromBody] ScriptRecordDto dto) + { + try + { + CancellationToken ct = HttpContext.RequestAborted; + + ScriptRecord record = dto.ToModel(); + _context.ScriptRecords.Add(record); + + await _context.SaveChangesAsync(ct); + _logger.LogInformation("Script record saved: {ExecId} by {Username}", record.ExecId, record.Username); + return Ok(); + } + catch (DbUpdateException ex) + { + _logger.LogError(ex, "Database error while saving script record"); + return StatusCode(503); + } + catch (Exception ex) + { + _logger.LogError(ex, "Unexpected error while saving script record"); + return StatusCode(500); + } + } + + /// + /// Adds event record to DB. + /// + /// Adding event records. + /// Returns adding event records task. + [HttpPost("events")] + [ProducesResponseType(200)] + [ProducesResponseType(500)] + [ProducesResponseType(503)] + public async Task PostEvent([FromBody] EventRecordDto dto) + { + try + { + CancellationToken ct = HttpContext.RequestAborted; + + EventRecord record = dto.ToModel(); + _context.EventRecords.Add(record); + + await _context.SaveChangesAsync(ct); + _logger.LogInformation("Event record saved: {Type} by {Username}", record.EventType, record.Username); + return Ok(); + } + catch (DbUpdateException ex) + { + _logger.LogError(ex, "Database error while saving an event record"); + return StatusCode(503); + } + catch (Exception ex) + { + _logger.LogError(ex, "Unexpected error while saving event record"); + return StatusCode(500); + } + } + + /// + /// Retrieves the current status. + /// + /// The current status as a status object. + [HttpGet("status")] + [ProducesResponseType(200)] + [ProducesResponseType(500)] + [ProducesResponseType(503)] + public async Task GetStatus() + { + try + { + CancellationToken ct = HttpContext.RequestAborted; + + bool canConnect = await _context.CanConnectAsync(ct); + string provider = _context.GetDbProvider(); + string version = await _context.GetDbVersionAsync(ct); + + Dictionary checks = new() + { + {provider, new StatusCheckDto {Status = canConnect ? "pass" : "fail", Version = version}} + }; + + StatusRecordDto status = new() + { + Status = canConnect ? "pass" : "fail", + ServiceId = _serviceInfo.ServiceId, + Version = typeof(TelemetryController).Assembly.GetName().Version?.ToString() ?? "2.0.0.0", + Checks = checks + }; + + return canConnect ? Ok(status) : StatusCode(503, status); + } + catch (Exception ex) + { + _logger.LogError(ex, "Error checking status"); + return StatusCode(500); + } + } + } +} \ No newline at end of file diff --git a/src/Telemetry.Api/Web/Middleware/ExceptionHandlingMiddleware.cs b/src/Telemetry.Api/Web/Middleware/ExceptionHandlingMiddleware.cs new file mode 100644 index 0000000..c8f9754 --- /dev/null +++ b/src/Telemetry.Api/Web/Middleware/ExceptionHandlingMiddleware.cs @@ -0,0 +1,27 @@ +namespace Telemetry.Api.Web.Middleware +{ + internal class ExceptionHandlingMiddleware + { + private readonly ILogger _logger; + private readonly RequestDelegate _next; + + public ExceptionHandlingMiddleware(RequestDelegate next, ILogger logger) + { + _next = next; + _logger = logger; + } + + public async Task Invoke(HttpContext context) + { + try + { + await _next(context); + } + catch (Exception ex) + { + _logger.LogError(ex, "Unhandled exception"); + context.Response.StatusCode = 500; + } + } + } +} \ No newline at end of file diff --git a/src/Telemetry.Api/appsettings.Development.json b/src/Telemetry.Api/appsettings.Development.json new file mode 100644 index 0000000..3e1a225 --- /dev/null +++ b/src/Telemetry.Api/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Information" + } + } +} diff --git a/src/Telemetry.Api/appsettings.json b/src/Telemetry.Api/appsettings.json new file mode 100644 index 0000000..4282acb --- /dev/null +++ b/src/Telemetry.Api/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Information" + } + }, + "AllowedHosts": "*" +} diff --git a/src/Telemetry.Migrations.Oracle/Migrations/20260330090657_InitOracle.Designer.cs b/src/Telemetry.Migrations.Oracle/Migrations/20260330090657_InitOracle.Designer.cs new file mode 100644 index 0000000..2d3e912 --- /dev/null +++ b/src/Telemetry.Migrations.Oracle/Migrations/20260330090657_InitOracle.Designer.cs @@ -0,0 +1,271 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Oracle.EntityFrameworkCore.Metadata; +using Telemetry.Api.Infrastructure.Persistence; + +#nullable disable + +namespace Telemetry.Migrations.Oracle.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20260330090657_InitOracle")] + partial class InitOracle + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "10.0.5") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + OracleModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Telemetry.Api.Domain.Models.EventRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("RAW(16)") + .HasColumnName("id"); + + b.Property("Cancellable") + .HasColumnType("BOOLEAN"); + + b.Property("Cancelled") + .HasColumnType("BOOLEAN") + .HasColumnName("cancelled"); + + b.Property("DocumentId") + .HasColumnType("NUMBER(10)") + .HasColumnName("docid"); + + b.Property("DocumentName") + .HasMaxLength(250) + .HasColumnType("NVARCHAR2(250)") + .HasColumnName("docname"); + + b.Property("DocumentPath") + .HasMaxLength(1024) + .HasColumnType("NVARCHAR2(1024)") + .HasColumnName("docpath"); + + b.Property("DocumentTemplate") + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("doctemplate"); + + b.Property("DocumentType") + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("doctype"); + + b.Property("EventArgs") + .HasMaxLength(8000) + .HasColumnType("NCLOB") + .HasColumnName("args"); + + b.Property("EventType") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("type"); + + b.Property("HandlerId") + .HasColumnType("RAW(16)") + .HasColumnName("handler_id"); + + b.Property("HostUsername") + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("host_user"); + + b.Property("Meta") + .IsRequired() + .HasColumnType("NVARCHAR2(2000)") + .HasColumnName("meta"); + + b.Property("ProjectName") + .HasMaxLength(250) + .HasColumnType("NVARCHAR2(250)") + .HasColumnName("projectname"); + + b.Property("ProjectNum") + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("projectnum"); + + b.Property("RevitBuild") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("revitbuild"); + + b.Property("RevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("revit"); + + b.Property("Status") + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("status"); + + b.Property("Timestamp") + .HasColumnType("TIMESTAMP(7) WITH TIME ZONE") + .HasColumnName("timestamp"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("username"); + + b.HasKey("Id"); + + b.ToTable("event_record", (string)null); + }); + + modelBuilder.Entity("Telemetry.Api.Domain.Models.ScriptRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("RAW(16)") + .HasColumnName("id"); + + b.Property("CloneName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("clone"); + + b.Property("CommandBundle") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("NVARCHAR2(250)") + .HasColumnName("commandbundle"); + + b.Property("CommandExtension") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("NVARCHAR2(250)") + .HasColumnName("commandextension"); + + b.Property("CommandName") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("NVARCHAR2(250)") + .HasColumnName("commandname"); + + b.Property("CommandResults") + .HasMaxLength(8000) + .HasColumnType("NCLOB") + .HasColumnName("commandresults"); + + b.Property("CommandUniqueName") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("NVARCHAR2(500)") + .HasColumnName("commanduniquename"); + + b.Property("DocumentName") + .HasMaxLength(250) + .HasColumnType("NVARCHAR2(250)") + .HasColumnName("docname"); + + b.Property("DocumentPath") + .HasMaxLength(1024) + .HasColumnType("NVARCHAR2(1024)") + .HasColumnName("docpath"); + + b.Property("ExecId") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("exec_id"); + + b.Property("ExecTimestamp") + .HasColumnType("TIMESTAMP(7) WITH TIME ZONE") + .HasColumnName("exec_timestamp"); + + b.Property("HostUsername") + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("host_user"); + + b.Property("IsConfig") + .HasColumnType("BOOLEAN") + .HasColumnName("config"); + + b.Property("IsDebug") + .HasColumnType("BOOLEAN") + .HasColumnName("debug"); + + b.Property("IsExecFromGui") + .HasColumnType("BOOLEAN") + .HasColumnName("from_gui"); + + b.Property("Meta") + .IsRequired() + .HasColumnType("NVARCHAR2(2000)") + .HasColumnName("meta"); + + b.Property("PyRevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("pyrevit"); + + b.Property("ResultCode") + .HasColumnType("NUMBER(10)") + .HasColumnName("resultcode"); + + b.Property("RevitBuild") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("revitbuild"); + + b.Property("RevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("revit"); + + b.Property("ScriptPath") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("NVARCHAR2(1024)") + .HasColumnName("scriptpath"); + + b.Property("SessionId") + .HasColumnType("RAW(16)") + .HasColumnName("sessionid"); + + b.Property("Timestamp") + .HasColumnType("TIMESTAMP(7) WITH TIME ZONE") + .HasColumnName("timestamp"); + + b.Property("Trace") + .IsRequired() + .HasColumnType("NVARCHAR2(2000)") + .HasColumnName("trace"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("username"); + + b.HasKey("Id"); + + b.ToTable("script_record", (string)null); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Telemetry.Migrations.Oracle/Migrations/20260330090657_InitOracle.cs b/src/Telemetry.Migrations.Oracle/Migrations/20260330090657_InitOracle.cs new file mode 100644 index 0000000..47879bb --- /dev/null +++ b/src/Telemetry.Migrations.Oracle/Migrations/20260330090657_InitOracle.cs @@ -0,0 +1,90 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Telemetry.Migrations.Oracle.Migrations +{ + /// + public partial class InitOracle : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "event_record", + columns: table => new + { + id = table.Column(type: "RAW(16)", nullable: false), + handler_id = table.Column(type: "RAW(16)", nullable: false), + meta = table.Column(type: "NVARCHAR2(2000)", nullable: false), + type = table.Column(type: "NVARCHAR2(100)", maxLength: 100, nullable: false), + status = table.Column(type: "NVARCHAR2(100)", maxLength: 100, nullable: true), + timestamp = table.Column(type: "TIMESTAMP(7) WITH TIME ZONE", nullable: false), + username = table.Column(type: "NVARCHAR2(100)", maxLength: 100, nullable: false), + host_user = table.Column(type: "NVARCHAR2(100)", maxLength: 100, nullable: true), + revitbuild = table.Column(type: "NVARCHAR2(100)", maxLength: 100, nullable: false), + revit = table.Column(type: "NVARCHAR2(100)", maxLength: 100, nullable: false), + cancelled = table.Column(type: "BOOLEAN", nullable: true), + Cancellable = table.Column(type: "BOOLEAN", nullable: true), + docid = table.Column(type: "NUMBER(10)", nullable: false), + doctype = table.Column(type: "NVARCHAR2(100)", maxLength: 100, nullable: true), + doctemplate = table.Column(type: "NVARCHAR2(100)", maxLength: 100, nullable: true), + docname = table.Column(type: "NVARCHAR2(250)", maxLength: 250, nullable: true), + docpath = table.Column(type: "NVARCHAR2(1024)", maxLength: 1024, nullable: true), + projectname = table.Column(type: "NVARCHAR2(250)", maxLength: 250, nullable: true), + projectnum = table.Column(type: "NVARCHAR2(100)", maxLength: 100, nullable: true), + args = table.Column(type: "NCLOB", maxLength: 8000, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_event_record", x => x.id); + }); + + migrationBuilder.CreateTable( + name: "script_record", + columns: table => new + { + id = table.Column(type: "RAW(16)", nullable: false), + sessionid = table.Column(type: "RAW(16)", nullable: false), + meta = table.Column(type: "NVARCHAR2(2000)", nullable: false), + timestamp = table.Column(type: "TIMESTAMP(7) WITH TIME ZONE", nullable: false), + username = table.Column(type: "NVARCHAR2(100)", maxLength: 100, nullable: false), + host_user = table.Column(type: "NVARCHAR2(100)", maxLength: 100, nullable: true), + revitbuild = table.Column(type: "NVARCHAR2(100)", maxLength: 100, nullable: false), + revit = table.Column(type: "NVARCHAR2(100)", maxLength: 100, nullable: false), + pyrevit = table.Column(type: "NVARCHAR2(100)", maxLength: 100, nullable: false), + clone = table.Column(type: "NVARCHAR2(100)", maxLength: 100, nullable: false), + debug = table.Column(type: "BOOLEAN", nullable: false), + config = table.Column(type: "BOOLEAN", nullable: false), + from_gui = table.Column(type: "BOOLEAN", nullable: false), + exec_id = table.Column(type: "NVARCHAR2(100)", maxLength: 100, nullable: false), + exec_timestamp = table.Column(type: "TIMESTAMP(7) WITH TIME ZONE", nullable: false), + commandbundle = table.Column(type: "NVARCHAR2(250)", maxLength: 250, nullable: false), + commandextension = table.Column(type: "NVARCHAR2(250)", maxLength: 250, nullable: false), + commandname = table.Column(type: "NVARCHAR2(250)", maxLength: 250, nullable: false), + commanduniquename = table.Column(type: "NVARCHAR2(500)", maxLength: 500, nullable: false), + docname = table.Column(type: "NVARCHAR2(250)", maxLength: 250, nullable: true), + docpath = table.Column(type: "NVARCHAR2(1024)", maxLength: 1024, nullable: true), + resultcode = table.Column(type: "NUMBER(10)", nullable: false), + scriptpath = table.Column(type: "NVARCHAR2(1024)", maxLength: 1024, nullable: false), + trace = table.Column(type: "NVARCHAR2(2000)", nullable: false), + commandresults = table.Column(type: "NCLOB", maxLength: 8000, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_script_record", x => x.id); + }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "event_record"); + + migrationBuilder.DropTable( + name: "script_record"); + } + } +} diff --git a/src/Telemetry.Migrations.Oracle/Migrations/ApplicationDbContextModelSnapshot.cs b/src/Telemetry.Migrations.Oracle/Migrations/ApplicationDbContextModelSnapshot.cs new file mode 100644 index 0000000..4da5e69 --- /dev/null +++ b/src/Telemetry.Migrations.Oracle/Migrations/ApplicationDbContextModelSnapshot.cs @@ -0,0 +1,268 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Oracle.EntityFrameworkCore.Metadata; +using Telemetry.Api.Infrastructure.Persistence; + +#nullable disable + +namespace Telemetry.Migrations.Oracle.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + partial class ApplicationDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "10.0.5") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + OracleModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Telemetry.Api.Domain.Models.EventRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("RAW(16)") + .HasColumnName("id"); + + b.Property("Cancellable") + .HasColumnType("BOOLEAN"); + + b.Property("Cancelled") + .HasColumnType("BOOLEAN") + .HasColumnName("cancelled"); + + b.Property("DocumentId") + .HasColumnType("NUMBER(10)") + .HasColumnName("docid"); + + b.Property("DocumentName") + .HasMaxLength(250) + .HasColumnType("NVARCHAR2(250)") + .HasColumnName("docname"); + + b.Property("DocumentPath") + .HasMaxLength(1024) + .HasColumnType("NVARCHAR2(1024)") + .HasColumnName("docpath"); + + b.Property("DocumentTemplate") + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("doctemplate"); + + b.Property("DocumentType") + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("doctype"); + + b.Property("EventArgs") + .HasMaxLength(8000) + .HasColumnType("NCLOB") + .HasColumnName("args"); + + b.Property("EventType") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("type"); + + b.Property("HandlerId") + .HasColumnType("RAW(16)") + .HasColumnName("handler_id"); + + b.Property("HostUsername") + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("host_user"); + + b.Property("Meta") + .IsRequired() + .HasColumnType("NVARCHAR2(2000)") + .HasColumnName("meta"); + + b.Property("ProjectName") + .HasMaxLength(250) + .HasColumnType("NVARCHAR2(250)") + .HasColumnName("projectname"); + + b.Property("ProjectNum") + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("projectnum"); + + b.Property("RevitBuild") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("revitbuild"); + + b.Property("RevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("revit"); + + b.Property("Status") + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("status"); + + b.Property("Timestamp") + .HasColumnType("TIMESTAMP(7) WITH TIME ZONE") + .HasColumnName("timestamp"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("username"); + + b.HasKey("Id"); + + b.ToTable("event_record", (string)null); + }); + + modelBuilder.Entity("Telemetry.Api.Domain.Models.ScriptRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("RAW(16)") + .HasColumnName("id"); + + b.Property("CloneName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("clone"); + + b.Property("CommandBundle") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("NVARCHAR2(250)") + .HasColumnName("commandbundle"); + + b.Property("CommandExtension") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("NVARCHAR2(250)") + .HasColumnName("commandextension"); + + b.Property("CommandName") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("NVARCHAR2(250)") + .HasColumnName("commandname"); + + b.Property("CommandResults") + .HasMaxLength(8000) + .HasColumnType("NCLOB") + .HasColumnName("commandresults"); + + b.Property("CommandUniqueName") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("NVARCHAR2(500)") + .HasColumnName("commanduniquename"); + + b.Property("DocumentName") + .HasMaxLength(250) + .HasColumnType("NVARCHAR2(250)") + .HasColumnName("docname"); + + b.Property("DocumentPath") + .HasMaxLength(1024) + .HasColumnType("NVARCHAR2(1024)") + .HasColumnName("docpath"); + + b.Property("ExecId") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("exec_id"); + + b.Property("ExecTimestamp") + .HasColumnType("TIMESTAMP(7) WITH TIME ZONE") + .HasColumnName("exec_timestamp"); + + b.Property("HostUsername") + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("host_user"); + + b.Property("IsConfig") + .HasColumnType("BOOLEAN") + .HasColumnName("config"); + + b.Property("IsDebug") + .HasColumnType("BOOLEAN") + .HasColumnName("debug"); + + b.Property("IsExecFromGui") + .HasColumnType("BOOLEAN") + .HasColumnName("from_gui"); + + b.Property("Meta") + .IsRequired() + .HasColumnType("NVARCHAR2(2000)") + .HasColumnName("meta"); + + b.Property("PyRevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("pyrevit"); + + b.Property("ResultCode") + .HasColumnType("NUMBER(10)") + .HasColumnName("resultcode"); + + b.Property("RevitBuild") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("revitbuild"); + + b.Property("RevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("revit"); + + b.Property("ScriptPath") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("NVARCHAR2(1024)") + .HasColumnName("scriptpath"); + + b.Property("SessionId") + .HasColumnType("RAW(16)") + .HasColumnName("sessionid"); + + b.Property("Timestamp") + .HasColumnType("TIMESTAMP(7) WITH TIME ZONE") + .HasColumnName("timestamp"); + + b.Property("Trace") + .IsRequired() + .HasColumnType("NVARCHAR2(2000)") + .HasColumnName("trace"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("username"); + + b.HasKey("Id"); + + b.ToTable("script_record", (string)null); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Telemetry.Migrations.Oracle/Telemetry.Migrations.Oracle.csproj b/src/Telemetry.Migrations.Oracle/Telemetry.Migrations.Oracle.csproj new file mode 100644 index 0000000..a4640d7 --- /dev/null +++ b/src/Telemetry.Migrations.Oracle/Telemetry.Migrations.Oracle.csproj @@ -0,0 +1,22 @@ + + + + Library + net10.0 + enable + enable + ..\..\src\Telemetry.Api\bin\ + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + diff --git a/src/Telemetry.Migrations.Postgres/Migrations/20260330090711_InitPostgres.Designer.cs b/src/Telemetry.Migrations.Postgres/Migrations/20260330090711_InitPostgres.Designer.cs new file mode 100644 index 0000000..a2baa5d --- /dev/null +++ b/src/Telemetry.Migrations.Postgres/Migrations/20260330090711_InitPostgres.Designer.cs @@ -0,0 +1,271 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using Telemetry.Api.Infrastructure.Persistence; + +#nullable disable + +namespace Telemetry.Migrations.Postgres.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20260330090711_InitPostgres")] + partial class InitPostgres + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "10.0.5") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Telemetry.Api.Domain.Models.EventRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("Cancellable") + .HasColumnType("boolean"); + + b.Property("Cancelled") + .HasColumnType("boolean") + .HasColumnName("cancelled"); + + b.Property("DocumentId") + .HasColumnType("integer") + .HasColumnName("docid"); + + b.Property("DocumentName") + .HasMaxLength(250) + .HasColumnType("character varying(250)") + .HasColumnName("docname"); + + b.Property("DocumentPath") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("docpath"); + + b.Property("DocumentTemplate") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("doctemplate"); + + b.Property("DocumentType") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("doctype"); + + b.Property("EventArgs") + .HasMaxLength(8000) + .HasColumnType("character varying(8000)") + .HasColumnName("args"); + + b.Property("EventType") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("type"); + + b.Property("HandlerId") + .HasColumnType("uuid") + .HasColumnName("handler_id"); + + b.Property("HostUsername") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("host_user"); + + b.Property("Meta") + .IsRequired() + .HasColumnType("text") + .HasColumnName("meta"); + + b.Property("ProjectName") + .HasMaxLength(250) + .HasColumnType("character varying(250)") + .HasColumnName("projectname"); + + b.Property("ProjectNum") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("projectnum"); + + b.Property("RevitBuild") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("revitbuild"); + + b.Property("RevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("revit"); + + b.Property("Status") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("status"); + + b.Property("Timestamp") + .HasColumnType("timestamp with time zone") + .HasColumnName("timestamp"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("username"); + + b.HasKey("Id"); + + b.ToTable("event_record", (string)null); + }); + + modelBuilder.Entity("Telemetry.Api.Domain.Models.ScriptRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("CloneName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("clone"); + + b.Property("CommandBundle") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)") + .HasColumnName("commandbundle"); + + b.Property("CommandExtension") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)") + .HasColumnName("commandextension"); + + b.Property("CommandName") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)") + .HasColumnName("commandname"); + + b.Property("CommandResults") + .HasMaxLength(8000) + .HasColumnType("character varying(8000)") + .HasColumnName("commandresults"); + + b.Property("CommandUniqueName") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("character varying(500)") + .HasColumnName("commanduniquename"); + + b.Property("DocumentName") + .HasMaxLength(250) + .HasColumnType("character varying(250)") + .HasColumnName("docname"); + + b.Property("DocumentPath") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("docpath"); + + b.Property("ExecId") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("exec_id"); + + b.Property("ExecTimestamp") + .HasColumnType("timestamp with time zone") + .HasColumnName("exec_timestamp"); + + b.Property("HostUsername") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("host_user"); + + b.Property("IsConfig") + .HasColumnType("boolean") + .HasColumnName("config"); + + b.Property("IsDebug") + .HasColumnType("boolean") + .HasColumnName("debug"); + + b.Property("IsExecFromGui") + .HasColumnType("boolean") + .HasColumnName("from_gui"); + + b.Property("Meta") + .IsRequired() + .HasColumnType("text") + .HasColumnName("meta"); + + b.Property("PyRevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("pyrevit"); + + b.Property("ResultCode") + .HasColumnType("integer") + .HasColumnName("resultcode"); + + b.Property("RevitBuild") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("revitbuild"); + + b.Property("RevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("revit"); + + b.Property("ScriptPath") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("scriptpath"); + + b.Property("SessionId") + .HasColumnType("uuid") + .HasColumnName("sessionid"); + + b.Property("Timestamp") + .HasColumnType("timestamp with time zone") + .HasColumnName("timestamp"); + + b.Property("Trace") + .IsRequired() + .HasColumnType("text") + .HasColumnName("trace"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("username"); + + b.HasKey("Id"); + + b.ToTable("script_record", (string)null); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Telemetry.Migrations.Postgres/Migrations/20260330090711_InitPostgres.cs b/src/Telemetry.Migrations.Postgres/Migrations/20260330090711_InitPostgres.cs new file mode 100644 index 0000000..2755cc2 --- /dev/null +++ b/src/Telemetry.Migrations.Postgres/Migrations/20260330090711_InitPostgres.cs @@ -0,0 +1,90 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Telemetry.Migrations.Postgres.Migrations +{ + /// + public partial class InitPostgres : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "event_record", + columns: table => new + { + id = table.Column(type: "uuid", nullable: false), + handler_id = table.Column(type: "uuid", nullable: false), + meta = table.Column(type: "text", nullable: false), + type = table.Column(type: "character varying(100)", maxLength: 100, nullable: false), + status = table.Column(type: "character varying(100)", maxLength: 100, nullable: true), + timestamp = table.Column(type: "timestamp with time zone", nullable: false), + username = table.Column(type: "character varying(100)", maxLength: 100, nullable: false), + host_user = table.Column(type: "character varying(100)", maxLength: 100, nullable: true), + revitbuild = table.Column(type: "character varying(100)", maxLength: 100, nullable: false), + revit = table.Column(type: "character varying(100)", maxLength: 100, nullable: false), + cancelled = table.Column(type: "boolean", nullable: true), + Cancellable = table.Column(type: "boolean", nullable: true), + docid = table.Column(type: "integer", nullable: false), + doctype = table.Column(type: "character varying(100)", maxLength: 100, nullable: true), + doctemplate = table.Column(type: "character varying(100)", maxLength: 100, nullable: true), + docname = table.Column(type: "character varying(250)", maxLength: 250, nullable: true), + docpath = table.Column(type: "character varying(1024)", maxLength: 1024, nullable: true), + projectname = table.Column(type: "character varying(250)", maxLength: 250, nullable: true), + projectnum = table.Column(type: "character varying(100)", maxLength: 100, nullable: true), + args = table.Column(type: "character varying(8000)", maxLength: 8000, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_event_record", x => x.id); + }); + + migrationBuilder.CreateTable( + name: "script_record", + columns: table => new + { + id = table.Column(type: "uuid", nullable: false), + sessionid = table.Column(type: "uuid", nullable: false), + meta = table.Column(type: "text", nullable: false), + timestamp = table.Column(type: "timestamp with time zone", nullable: false), + username = table.Column(type: "character varying(100)", maxLength: 100, nullable: false), + host_user = table.Column(type: "character varying(100)", maxLength: 100, nullable: true), + revitbuild = table.Column(type: "character varying(100)", maxLength: 100, nullable: false), + revit = table.Column(type: "character varying(100)", maxLength: 100, nullable: false), + pyrevit = table.Column(type: "character varying(100)", maxLength: 100, nullable: false), + clone = table.Column(type: "character varying(100)", maxLength: 100, nullable: false), + debug = table.Column(type: "boolean", nullable: false), + config = table.Column(type: "boolean", nullable: false), + from_gui = table.Column(type: "boolean", nullable: false), + exec_id = table.Column(type: "character varying(100)", maxLength: 100, nullable: false), + exec_timestamp = table.Column(type: "timestamp with time zone", nullable: false), + commandbundle = table.Column(type: "character varying(250)", maxLength: 250, nullable: false), + commandextension = table.Column(type: "character varying(250)", maxLength: 250, nullable: false), + commandname = table.Column(type: "character varying(250)", maxLength: 250, nullable: false), + commanduniquename = table.Column(type: "character varying(500)", maxLength: 500, nullable: false), + docname = table.Column(type: "character varying(250)", maxLength: 250, nullable: true), + docpath = table.Column(type: "character varying(1024)", maxLength: 1024, nullable: true), + resultcode = table.Column(type: "integer", nullable: false), + scriptpath = table.Column(type: "character varying(1024)", maxLength: 1024, nullable: false), + trace = table.Column(type: "text", nullable: false), + commandresults = table.Column(type: "character varying(8000)", maxLength: 8000, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_script_record", x => x.id); + }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "event_record"); + + migrationBuilder.DropTable( + name: "script_record"); + } + } +} diff --git a/src/Telemetry.Migrations.Postgres/Migrations/ApplicationDbContextModelSnapshot.cs b/src/Telemetry.Migrations.Postgres/Migrations/ApplicationDbContextModelSnapshot.cs new file mode 100644 index 0000000..89d9395 --- /dev/null +++ b/src/Telemetry.Migrations.Postgres/Migrations/ApplicationDbContextModelSnapshot.cs @@ -0,0 +1,268 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using Telemetry.Api.Infrastructure.Persistence; + +#nullable disable + +namespace Telemetry.Migrations.Postgres.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + partial class ApplicationDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "10.0.5") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Telemetry.Api.Domain.Models.EventRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("Cancellable") + .HasColumnType("boolean"); + + b.Property("Cancelled") + .HasColumnType("boolean") + .HasColumnName("cancelled"); + + b.Property("DocumentId") + .HasColumnType("integer") + .HasColumnName("docid"); + + b.Property("DocumentName") + .HasMaxLength(250) + .HasColumnType("character varying(250)") + .HasColumnName("docname"); + + b.Property("DocumentPath") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("docpath"); + + b.Property("DocumentTemplate") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("doctemplate"); + + b.Property("DocumentType") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("doctype"); + + b.Property("EventArgs") + .HasMaxLength(8000) + .HasColumnType("character varying(8000)") + .HasColumnName("args"); + + b.Property("EventType") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("type"); + + b.Property("HandlerId") + .HasColumnType("uuid") + .HasColumnName("handler_id"); + + b.Property("HostUsername") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("host_user"); + + b.Property("Meta") + .IsRequired() + .HasColumnType("text") + .HasColumnName("meta"); + + b.Property("ProjectName") + .HasMaxLength(250) + .HasColumnType("character varying(250)") + .HasColumnName("projectname"); + + b.Property("ProjectNum") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("projectnum"); + + b.Property("RevitBuild") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("revitbuild"); + + b.Property("RevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("revit"); + + b.Property("Status") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("status"); + + b.Property("Timestamp") + .HasColumnType("timestamp with time zone") + .HasColumnName("timestamp"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("username"); + + b.HasKey("Id"); + + b.ToTable("event_record", (string)null); + }); + + modelBuilder.Entity("Telemetry.Api.Domain.Models.ScriptRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("CloneName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("clone"); + + b.Property("CommandBundle") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)") + .HasColumnName("commandbundle"); + + b.Property("CommandExtension") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)") + .HasColumnName("commandextension"); + + b.Property("CommandName") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)") + .HasColumnName("commandname"); + + b.Property("CommandResults") + .HasMaxLength(8000) + .HasColumnType("character varying(8000)") + .HasColumnName("commandresults"); + + b.Property("CommandUniqueName") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("character varying(500)") + .HasColumnName("commanduniquename"); + + b.Property("DocumentName") + .HasMaxLength(250) + .HasColumnType("character varying(250)") + .HasColumnName("docname"); + + b.Property("DocumentPath") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("docpath"); + + b.Property("ExecId") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("exec_id"); + + b.Property("ExecTimestamp") + .HasColumnType("timestamp with time zone") + .HasColumnName("exec_timestamp"); + + b.Property("HostUsername") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("host_user"); + + b.Property("IsConfig") + .HasColumnType("boolean") + .HasColumnName("config"); + + b.Property("IsDebug") + .HasColumnType("boolean") + .HasColumnName("debug"); + + b.Property("IsExecFromGui") + .HasColumnType("boolean") + .HasColumnName("from_gui"); + + b.Property("Meta") + .IsRequired() + .HasColumnType("text") + .HasColumnName("meta"); + + b.Property("PyRevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("pyrevit"); + + b.Property("ResultCode") + .HasColumnType("integer") + .HasColumnName("resultcode"); + + b.Property("RevitBuild") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("revitbuild"); + + b.Property("RevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("revit"); + + b.Property("ScriptPath") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("scriptpath"); + + b.Property("SessionId") + .HasColumnType("uuid") + .HasColumnName("sessionid"); + + b.Property("Timestamp") + .HasColumnType("timestamp with time zone") + .HasColumnName("timestamp"); + + b.Property("Trace") + .IsRequired() + .HasColumnType("text") + .HasColumnName("trace"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("username"); + + b.HasKey("Id"); + + b.ToTable("script_record", (string)null); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Telemetry.Migrations.Postgres/Telemetry.Migrations.Postgres.csproj b/src/Telemetry.Migrations.Postgres/Telemetry.Migrations.Postgres.csproj new file mode 100644 index 0000000..a4640d7 --- /dev/null +++ b/src/Telemetry.Migrations.Postgres/Telemetry.Migrations.Postgres.csproj @@ -0,0 +1,22 @@ + + + + Library + net10.0 + enable + enable + ..\..\src\Telemetry.Api\bin\ + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + diff --git a/src/Telemetry.Migrations.SqlServer/Migrations/20260330090733_InitSqlServer.Designer.cs b/src/Telemetry.Migrations.SqlServer/Migrations/20260330090733_InitSqlServer.Designer.cs new file mode 100644 index 0000000..28e8881 --- /dev/null +++ b/src/Telemetry.Migrations.SqlServer/Migrations/20260330090733_InitSqlServer.Designer.cs @@ -0,0 +1,271 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Telemetry.Api.Infrastructure.Persistence; + +#nullable disable + +namespace Telemetry.Migrations.SqlServer.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20260330090733_InitSqlServer")] + partial class InitSqlServer + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "10.0.5") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Telemetry.Api.Domain.Models.EventRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnName("id"); + + b.Property("Cancellable") + .HasColumnType("bit"); + + b.Property("Cancelled") + .HasColumnType("bit") + .HasColumnName("cancelled"); + + b.Property("DocumentId") + .HasColumnType("int") + .HasColumnName("docid"); + + b.Property("DocumentName") + .HasMaxLength(250) + .HasColumnType("nvarchar(250)") + .HasColumnName("docname"); + + b.Property("DocumentPath") + .HasMaxLength(1024) + .HasColumnType("nvarchar(1024)") + .HasColumnName("docpath"); + + b.Property("DocumentTemplate") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("doctemplate"); + + b.Property("DocumentType") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("doctype"); + + b.Property("EventArgs") + .HasMaxLength(8000) + .HasColumnType("nvarchar(max)") + .HasColumnName("args"); + + b.Property("EventType") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("type"); + + b.Property("HandlerId") + .HasColumnType("uniqueidentifier") + .HasColumnName("handler_id"); + + b.Property("HostUsername") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("host_user"); + + b.Property("Meta") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("meta"); + + b.Property("ProjectName") + .HasMaxLength(250) + .HasColumnType("nvarchar(250)") + .HasColumnName("projectname"); + + b.Property("ProjectNum") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("projectnum"); + + b.Property("RevitBuild") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("revitbuild"); + + b.Property("RevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("revit"); + + b.Property("Status") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("status"); + + b.Property("Timestamp") + .HasColumnType("datetimeoffset") + .HasColumnName("timestamp"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("username"); + + b.HasKey("Id"); + + b.ToTable("event_record", (string)null); + }); + + modelBuilder.Entity("Telemetry.Api.Domain.Models.ScriptRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnName("id"); + + b.Property("CloneName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("clone"); + + b.Property("CommandBundle") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("nvarchar(250)") + .HasColumnName("commandbundle"); + + b.Property("CommandExtension") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("nvarchar(250)") + .HasColumnName("commandextension"); + + b.Property("CommandName") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("nvarchar(250)") + .HasColumnName("commandname"); + + b.Property("CommandResults") + .HasMaxLength(8000) + .HasColumnType("nvarchar(max)") + .HasColumnName("commandresults"); + + b.Property("CommandUniqueName") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("nvarchar(500)") + .HasColumnName("commanduniquename"); + + b.Property("DocumentName") + .HasMaxLength(250) + .HasColumnType("nvarchar(250)") + .HasColumnName("docname"); + + b.Property("DocumentPath") + .HasMaxLength(1024) + .HasColumnType("nvarchar(1024)") + .HasColumnName("docpath"); + + b.Property("ExecId") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("exec_id"); + + b.Property("ExecTimestamp") + .HasColumnType("datetimeoffset") + .HasColumnName("exec_timestamp"); + + b.Property("HostUsername") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("host_user"); + + b.Property("IsConfig") + .HasColumnType("bit") + .HasColumnName("config"); + + b.Property("IsDebug") + .HasColumnType("bit") + .HasColumnName("debug"); + + b.Property("IsExecFromGui") + .HasColumnType("bit") + .HasColumnName("from_gui"); + + b.Property("Meta") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("meta"); + + b.Property("PyRevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("pyrevit"); + + b.Property("ResultCode") + .HasColumnType("int") + .HasColumnName("resultcode"); + + b.Property("RevitBuild") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("revitbuild"); + + b.Property("RevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("revit"); + + b.Property("ScriptPath") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("nvarchar(1024)") + .HasColumnName("scriptpath"); + + b.Property("SessionId") + .HasColumnType("uniqueidentifier") + .HasColumnName("sessionid"); + + b.Property("Timestamp") + .HasColumnType("datetimeoffset") + .HasColumnName("timestamp"); + + b.Property("Trace") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("trace"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("username"); + + b.HasKey("Id"); + + b.ToTable("script_record", (string)null); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Telemetry.Migrations.SqlServer/Migrations/20260330090733_InitSqlServer.cs b/src/Telemetry.Migrations.SqlServer/Migrations/20260330090733_InitSqlServer.cs new file mode 100644 index 0000000..bb9b7b6 --- /dev/null +++ b/src/Telemetry.Migrations.SqlServer/Migrations/20260330090733_InitSqlServer.cs @@ -0,0 +1,90 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Telemetry.Migrations.SqlServer.Migrations +{ + /// + public partial class InitSqlServer : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "event_record", + columns: table => new + { + id = table.Column(type: "uniqueidentifier", nullable: false), + handler_id = table.Column(type: "uniqueidentifier", nullable: false), + meta = table.Column(type: "nvarchar(max)", nullable: false), + type = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: false), + status = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: true), + timestamp = table.Column(type: "datetimeoffset", nullable: false), + username = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: false), + host_user = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: true), + revitbuild = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: false), + revit = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: false), + cancelled = table.Column(type: "bit", nullable: true), + Cancellable = table.Column(type: "bit", nullable: true), + docid = table.Column(type: "int", nullable: false), + doctype = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: true), + doctemplate = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: true), + docname = table.Column(type: "nvarchar(250)", maxLength: 250, nullable: true), + docpath = table.Column(type: "nvarchar(1024)", maxLength: 1024, nullable: true), + projectname = table.Column(type: "nvarchar(250)", maxLength: 250, nullable: true), + projectnum = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: true), + args = table.Column(type: "nvarchar(max)", maxLength: 8000, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_event_record", x => x.id); + }); + + migrationBuilder.CreateTable( + name: "script_record", + columns: table => new + { + id = table.Column(type: "uniqueidentifier", nullable: false), + sessionid = table.Column(type: "uniqueidentifier", nullable: false), + meta = table.Column(type: "nvarchar(max)", nullable: false), + timestamp = table.Column(type: "datetimeoffset", nullable: false), + username = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: false), + host_user = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: true), + revitbuild = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: false), + revit = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: false), + pyrevit = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: false), + clone = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: false), + debug = table.Column(type: "bit", nullable: false), + config = table.Column(type: "bit", nullable: false), + from_gui = table.Column(type: "bit", nullable: false), + exec_id = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: false), + exec_timestamp = table.Column(type: "datetimeoffset", nullable: false), + commandbundle = table.Column(type: "nvarchar(250)", maxLength: 250, nullable: false), + commandextension = table.Column(type: "nvarchar(250)", maxLength: 250, nullable: false), + commandname = table.Column(type: "nvarchar(250)", maxLength: 250, nullable: false), + commanduniquename = table.Column(type: "nvarchar(500)", maxLength: 500, nullable: false), + docname = table.Column(type: "nvarchar(250)", maxLength: 250, nullable: true), + docpath = table.Column(type: "nvarchar(1024)", maxLength: 1024, nullable: true), + resultcode = table.Column(type: "int", nullable: false), + scriptpath = table.Column(type: "nvarchar(1024)", maxLength: 1024, nullable: false), + trace = table.Column(type: "nvarchar(max)", nullable: false), + commandresults = table.Column(type: "nvarchar(max)", maxLength: 8000, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_script_record", x => x.id); + }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "event_record"); + + migrationBuilder.DropTable( + name: "script_record"); + } + } +} diff --git a/src/Telemetry.Migrations.SqlServer/Migrations/ApplicationDbContextModelSnapshot.cs b/src/Telemetry.Migrations.SqlServer/Migrations/ApplicationDbContextModelSnapshot.cs new file mode 100644 index 0000000..e40673d --- /dev/null +++ b/src/Telemetry.Migrations.SqlServer/Migrations/ApplicationDbContextModelSnapshot.cs @@ -0,0 +1,268 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Telemetry.Api.Infrastructure.Persistence; + +#nullable disable + +namespace Telemetry.Migrations.SqlServer.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + partial class ApplicationDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "10.0.5") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Telemetry.Api.Domain.Models.EventRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnName("id"); + + b.Property("Cancellable") + .HasColumnType("bit"); + + b.Property("Cancelled") + .HasColumnType("bit") + .HasColumnName("cancelled"); + + b.Property("DocumentId") + .HasColumnType("int") + .HasColumnName("docid"); + + b.Property("DocumentName") + .HasMaxLength(250) + .HasColumnType("nvarchar(250)") + .HasColumnName("docname"); + + b.Property("DocumentPath") + .HasMaxLength(1024) + .HasColumnType("nvarchar(1024)") + .HasColumnName("docpath"); + + b.Property("DocumentTemplate") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("doctemplate"); + + b.Property("DocumentType") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("doctype"); + + b.Property("EventArgs") + .HasMaxLength(8000) + .HasColumnType("nvarchar(max)") + .HasColumnName("args"); + + b.Property("EventType") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("type"); + + b.Property("HandlerId") + .HasColumnType("uniqueidentifier") + .HasColumnName("handler_id"); + + b.Property("HostUsername") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("host_user"); + + b.Property("Meta") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("meta"); + + b.Property("ProjectName") + .HasMaxLength(250) + .HasColumnType("nvarchar(250)") + .HasColumnName("projectname"); + + b.Property("ProjectNum") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("projectnum"); + + b.Property("RevitBuild") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("revitbuild"); + + b.Property("RevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("revit"); + + b.Property("Status") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("status"); + + b.Property("Timestamp") + .HasColumnType("datetimeoffset") + .HasColumnName("timestamp"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("username"); + + b.HasKey("Id"); + + b.ToTable("event_record", (string)null); + }); + + modelBuilder.Entity("Telemetry.Api.Domain.Models.ScriptRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnName("id"); + + b.Property("CloneName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("clone"); + + b.Property("CommandBundle") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("nvarchar(250)") + .HasColumnName("commandbundle"); + + b.Property("CommandExtension") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("nvarchar(250)") + .HasColumnName("commandextension"); + + b.Property("CommandName") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("nvarchar(250)") + .HasColumnName("commandname"); + + b.Property("CommandResults") + .HasMaxLength(8000) + .HasColumnType("nvarchar(max)") + .HasColumnName("commandresults"); + + b.Property("CommandUniqueName") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("nvarchar(500)") + .HasColumnName("commanduniquename"); + + b.Property("DocumentName") + .HasMaxLength(250) + .HasColumnType("nvarchar(250)") + .HasColumnName("docname"); + + b.Property("DocumentPath") + .HasMaxLength(1024) + .HasColumnType("nvarchar(1024)") + .HasColumnName("docpath"); + + b.Property("ExecId") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("exec_id"); + + b.Property("ExecTimestamp") + .HasColumnType("datetimeoffset") + .HasColumnName("exec_timestamp"); + + b.Property("HostUsername") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("host_user"); + + b.Property("IsConfig") + .HasColumnType("bit") + .HasColumnName("config"); + + b.Property("IsDebug") + .HasColumnType("bit") + .HasColumnName("debug"); + + b.Property("IsExecFromGui") + .HasColumnType("bit") + .HasColumnName("from_gui"); + + b.Property("Meta") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("meta"); + + b.Property("PyRevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("pyrevit"); + + b.Property("ResultCode") + .HasColumnType("int") + .HasColumnName("resultcode"); + + b.Property("RevitBuild") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("revitbuild"); + + b.Property("RevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("revit"); + + b.Property("ScriptPath") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("nvarchar(1024)") + .HasColumnName("scriptpath"); + + b.Property("SessionId") + .HasColumnType("uniqueidentifier") + .HasColumnName("sessionid"); + + b.Property("Timestamp") + .HasColumnType("datetimeoffset") + .HasColumnName("timestamp"); + + b.Property("Trace") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("trace"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("username"); + + b.HasKey("Id"); + + b.ToTable("script_record", (string)null); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Telemetry.Migrations.SqlServer/Telemetry.Migrations.SqlServer.csproj b/src/Telemetry.Migrations.SqlServer/Telemetry.Migrations.SqlServer.csproj new file mode 100644 index 0000000..a4640d7 --- /dev/null +++ b/src/Telemetry.Migrations.SqlServer/Telemetry.Migrations.SqlServer.csproj @@ -0,0 +1,22 @@ + + + + Library + net10.0 + enable + enable + ..\..\src\Telemetry.Api\bin\ + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + diff --git a/src/Telemetry.Migrations.Sqlite/Migrations/20260330090723_InitSqlite.Designer.cs b/src/Telemetry.Migrations.Sqlite/Migrations/20260330090723_InitSqlite.Designer.cs new file mode 100644 index 0000000..f23cca0 --- /dev/null +++ b/src/Telemetry.Migrations.Sqlite/Migrations/20260330090723_InitSqlite.Designer.cs @@ -0,0 +1,266 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Telemetry.Api.Infrastructure.Persistence; + +#nullable disable + +namespace Telemetry.Migrations.Sqlite.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20260330090723_InitSqlite")] + partial class InitSqlite + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "10.0.5"); + + modelBuilder.Entity("Telemetry.Api.Domain.Models.EventRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT") + .HasColumnName("id"); + + b.Property("Cancellable") + .HasColumnType("INTEGER"); + + b.Property("Cancelled") + .HasColumnType("INTEGER") + .HasColumnName("cancelled"); + + b.Property("DocumentId") + .HasColumnType("INTEGER") + .HasColumnName("docid"); + + b.Property("DocumentName") + .HasMaxLength(250) + .HasColumnType("TEXT") + .HasColumnName("docname"); + + b.Property("DocumentPath") + .HasMaxLength(1024) + .HasColumnType("TEXT") + .HasColumnName("docpath"); + + b.Property("DocumentTemplate") + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("doctemplate"); + + b.Property("DocumentType") + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("doctype"); + + b.Property("EventArgs") + .HasMaxLength(8000) + .HasColumnType("TEXT") + .HasColumnName("args"); + + b.Property("EventType") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("type"); + + b.Property("HandlerId") + .HasColumnType("TEXT") + .HasColumnName("handler_id"); + + b.Property("HostUsername") + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("host_user"); + + b.Property("Meta") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("meta"); + + b.Property("ProjectName") + .HasMaxLength(250) + .HasColumnType("TEXT") + .HasColumnName("projectname"); + + b.Property("ProjectNum") + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("projectnum"); + + b.Property("RevitBuild") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("revitbuild"); + + b.Property("RevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("revit"); + + b.Property("Status") + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("status"); + + b.Property("Timestamp") + .HasColumnType("TEXT") + .HasColumnName("timestamp"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("username"); + + b.HasKey("Id"); + + b.ToTable("event_record", (string)null); + }); + + modelBuilder.Entity("Telemetry.Api.Domain.Models.ScriptRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT") + .HasColumnName("id"); + + b.Property("CloneName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("clone"); + + b.Property("CommandBundle") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("TEXT") + .HasColumnName("commandbundle"); + + b.Property("CommandExtension") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("TEXT") + .HasColumnName("commandextension"); + + b.Property("CommandName") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("TEXT") + .HasColumnName("commandname"); + + b.Property("CommandResults") + .HasMaxLength(8000) + .HasColumnType("TEXT") + .HasColumnName("commandresults"); + + b.Property("CommandUniqueName") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("TEXT") + .HasColumnName("commanduniquename"); + + b.Property("DocumentName") + .HasMaxLength(250) + .HasColumnType("TEXT") + .HasColumnName("docname"); + + b.Property("DocumentPath") + .HasMaxLength(1024) + .HasColumnType("TEXT") + .HasColumnName("docpath"); + + b.Property("ExecId") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("exec_id"); + + b.Property("ExecTimestamp") + .HasColumnType("TEXT") + .HasColumnName("exec_timestamp"); + + b.Property("HostUsername") + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("host_user"); + + b.Property("IsConfig") + .HasColumnType("INTEGER") + .HasColumnName("config"); + + b.Property("IsDebug") + .HasColumnType("INTEGER") + .HasColumnName("debug"); + + b.Property("IsExecFromGui") + .HasColumnType("INTEGER") + .HasColumnName("from_gui"); + + b.Property("Meta") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("meta"); + + b.Property("PyRevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("pyrevit"); + + b.Property("ResultCode") + .HasColumnType("INTEGER") + .HasColumnName("resultcode"); + + b.Property("RevitBuild") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("revitbuild"); + + b.Property("RevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("revit"); + + b.Property("ScriptPath") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("TEXT") + .HasColumnName("scriptpath"); + + b.Property("SessionId") + .HasColumnType("TEXT") + .HasColumnName("sessionid"); + + b.Property("Timestamp") + .HasColumnType("TEXT") + .HasColumnName("timestamp"); + + b.Property("Trace") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("trace"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("username"); + + b.HasKey("Id"); + + b.ToTable("script_record", (string)null); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Telemetry.Migrations.Sqlite/Migrations/20260330090723_InitSqlite.cs b/src/Telemetry.Migrations.Sqlite/Migrations/20260330090723_InitSqlite.cs new file mode 100644 index 0000000..cf58817 --- /dev/null +++ b/src/Telemetry.Migrations.Sqlite/Migrations/20260330090723_InitSqlite.cs @@ -0,0 +1,90 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Telemetry.Migrations.Sqlite.Migrations +{ + /// + public partial class InitSqlite : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "event_record", + columns: table => new + { + id = table.Column(type: "TEXT", nullable: false), + handler_id = table.Column(type: "TEXT", nullable: false), + meta = table.Column(type: "TEXT", nullable: false), + type = table.Column(type: "TEXT", maxLength: 100, nullable: false), + status = table.Column(type: "TEXT", maxLength: 100, nullable: true), + timestamp = table.Column(type: "TEXT", nullable: false), + username = table.Column(type: "TEXT", maxLength: 100, nullable: false), + host_user = table.Column(type: "TEXT", maxLength: 100, nullable: true), + revitbuild = table.Column(type: "TEXT", maxLength: 100, nullable: false), + revit = table.Column(type: "TEXT", maxLength: 100, nullable: false), + cancelled = table.Column(type: "INTEGER", nullable: true), + Cancellable = table.Column(type: "INTEGER", nullable: true), + docid = table.Column(type: "INTEGER", nullable: false), + doctype = table.Column(type: "TEXT", maxLength: 100, nullable: true), + doctemplate = table.Column(type: "TEXT", maxLength: 100, nullable: true), + docname = table.Column(type: "TEXT", maxLength: 250, nullable: true), + docpath = table.Column(type: "TEXT", maxLength: 1024, nullable: true), + projectname = table.Column(type: "TEXT", maxLength: 250, nullable: true), + projectnum = table.Column(type: "TEXT", maxLength: 100, nullable: true), + args = table.Column(type: "TEXT", maxLength: 8000, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_event_record", x => x.id); + }); + + migrationBuilder.CreateTable( + name: "script_record", + columns: table => new + { + id = table.Column(type: "TEXT", nullable: false), + sessionid = table.Column(type: "TEXT", nullable: false), + meta = table.Column(type: "TEXT", nullable: false), + timestamp = table.Column(type: "TEXT", nullable: false), + username = table.Column(type: "TEXT", maxLength: 100, nullable: false), + host_user = table.Column(type: "TEXT", maxLength: 100, nullable: true), + revitbuild = table.Column(type: "TEXT", maxLength: 100, nullable: false), + revit = table.Column(type: "TEXT", maxLength: 100, nullable: false), + pyrevit = table.Column(type: "TEXT", maxLength: 100, nullable: false), + clone = table.Column(type: "TEXT", maxLength: 100, nullable: false), + debug = table.Column(type: "INTEGER", nullable: false), + config = table.Column(type: "INTEGER", nullable: false), + from_gui = table.Column(type: "INTEGER", nullable: false), + exec_id = table.Column(type: "TEXT", maxLength: 100, nullable: false), + exec_timestamp = table.Column(type: "TEXT", nullable: false), + commandbundle = table.Column(type: "TEXT", maxLength: 250, nullable: false), + commandextension = table.Column(type: "TEXT", maxLength: 250, nullable: false), + commandname = table.Column(type: "TEXT", maxLength: 250, nullable: false), + commanduniquename = table.Column(type: "TEXT", maxLength: 500, nullable: false), + docname = table.Column(type: "TEXT", maxLength: 250, nullable: true), + docpath = table.Column(type: "TEXT", maxLength: 1024, nullable: true), + resultcode = table.Column(type: "INTEGER", nullable: false), + scriptpath = table.Column(type: "TEXT", maxLength: 1024, nullable: false), + trace = table.Column(type: "TEXT", nullable: false), + commandresults = table.Column(type: "TEXT", maxLength: 8000, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_script_record", x => x.id); + }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "event_record"); + + migrationBuilder.DropTable( + name: "script_record"); + } + } +} diff --git a/src/Telemetry.Migrations.Sqlite/Migrations/ApplicationDbContextModelSnapshot.cs b/src/Telemetry.Migrations.Sqlite/Migrations/ApplicationDbContextModelSnapshot.cs new file mode 100644 index 0000000..0cedbb7 --- /dev/null +++ b/src/Telemetry.Migrations.Sqlite/Migrations/ApplicationDbContextModelSnapshot.cs @@ -0,0 +1,263 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Telemetry.Api.Infrastructure.Persistence; + +#nullable disable + +namespace Telemetry.Migrations.Sqlite.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + partial class ApplicationDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "10.0.5"); + + modelBuilder.Entity("Telemetry.Api.Domain.Models.EventRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT") + .HasColumnName("id"); + + b.Property("Cancellable") + .HasColumnType("INTEGER"); + + b.Property("Cancelled") + .HasColumnType("INTEGER") + .HasColumnName("cancelled"); + + b.Property("DocumentId") + .HasColumnType("INTEGER") + .HasColumnName("docid"); + + b.Property("DocumentName") + .HasMaxLength(250) + .HasColumnType("TEXT") + .HasColumnName("docname"); + + b.Property("DocumentPath") + .HasMaxLength(1024) + .HasColumnType("TEXT") + .HasColumnName("docpath"); + + b.Property("DocumentTemplate") + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("doctemplate"); + + b.Property("DocumentType") + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("doctype"); + + b.Property("EventArgs") + .HasMaxLength(8000) + .HasColumnType("TEXT") + .HasColumnName("args"); + + b.Property("EventType") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("type"); + + b.Property("HandlerId") + .HasColumnType("TEXT") + .HasColumnName("handler_id"); + + b.Property("HostUsername") + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("host_user"); + + b.Property("Meta") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("meta"); + + b.Property("ProjectName") + .HasMaxLength(250) + .HasColumnType("TEXT") + .HasColumnName("projectname"); + + b.Property("ProjectNum") + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("projectnum"); + + b.Property("RevitBuild") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("revitbuild"); + + b.Property("RevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("revit"); + + b.Property("Status") + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("status"); + + b.Property("Timestamp") + .HasColumnType("TEXT") + .HasColumnName("timestamp"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("username"); + + b.HasKey("Id"); + + b.ToTable("event_record", (string)null); + }); + + modelBuilder.Entity("Telemetry.Api.Domain.Models.ScriptRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT") + .HasColumnName("id"); + + b.Property("CloneName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("clone"); + + b.Property("CommandBundle") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("TEXT") + .HasColumnName("commandbundle"); + + b.Property("CommandExtension") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("TEXT") + .HasColumnName("commandextension"); + + b.Property("CommandName") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("TEXT") + .HasColumnName("commandname"); + + b.Property("CommandResults") + .HasMaxLength(8000) + .HasColumnType("TEXT") + .HasColumnName("commandresults"); + + b.Property("CommandUniqueName") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("TEXT") + .HasColumnName("commanduniquename"); + + b.Property("DocumentName") + .HasMaxLength(250) + .HasColumnType("TEXT") + .HasColumnName("docname"); + + b.Property("DocumentPath") + .HasMaxLength(1024) + .HasColumnType("TEXT") + .HasColumnName("docpath"); + + b.Property("ExecId") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("exec_id"); + + b.Property("ExecTimestamp") + .HasColumnType("TEXT") + .HasColumnName("exec_timestamp"); + + b.Property("HostUsername") + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("host_user"); + + b.Property("IsConfig") + .HasColumnType("INTEGER") + .HasColumnName("config"); + + b.Property("IsDebug") + .HasColumnType("INTEGER") + .HasColumnName("debug"); + + b.Property("IsExecFromGui") + .HasColumnType("INTEGER") + .HasColumnName("from_gui"); + + b.Property("Meta") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("meta"); + + b.Property("PyRevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("pyrevit"); + + b.Property("ResultCode") + .HasColumnType("INTEGER") + .HasColumnName("resultcode"); + + b.Property("RevitBuild") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("revitbuild"); + + b.Property("RevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("revit"); + + b.Property("ScriptPath") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("TEXT") + .HasColumnName("scriptpath"); + + b.Property("SessionId") + .HasColumnType("TEXT") + .HasColumnName("sessionid"); + + b.Property("Timestamp") + .HasColumnType("TEXT") + .HasColumnName("timestamp"); + + b.Property("Trace") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("trace"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("username"); + + b.HasKey("Id"); + + b.ToTable("script_record", (string)null); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Telemetry.Migrations.Sqlite/Telemetry.Migrations.Sqlite.csproj b/src/Telemetry.Migrations.Sqlite/Telemetry.Migrations.Sqlite.csproj new file mode 100644 index 0000000..a4640d7 --- /dev/null +++ b/src/Telemetry.Migrations.Sqlite/Telemetry.Migrations.Sqlite.csproj @@ -0,0 +1,22 @@ + + + + Library + net10.0 + enable + enable + ..\..\src\Telemetry.Api\bin\ + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + diff --git a/telemetry-server.slnx b/telemetry-server.slnx new file mode 100644 index 0000000..7293b6c --- /dev/null +++ b/telemetry-server.slnx @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/tests/Telemetry.Api.IntegrationTests/BaseIntegrationTest.cs b/tests/Telemetry.Api.IntegrationTests/BaseIntegrationTest.cs new file mode 100644 index 0000000..ddadda2 --- /dev/null +++ b/tests/Telemetry.Api.IntegrationTests/BaseIntegrationTest.cs @@ -0,0 +1,108 @@ +using Microsoft.AspNetCore.Mvc.Testing; +using Microsoft.AspNetCore.TestHost; +using Telemetry.Api.Application.DTOs; +using TUnit.Core.Interfaces; + +namespace Telemetry.Api.IntegrationTests +{ + public abstract class BaseIntegrationTest : WebApplicationFactory, IAsyncInitializer, IAsyncDisposable + { + protected HttpClient Client { get; private set; } = null!; + + protected abstract string DbProvider { get; } + protected abstract string ConnectionString { get; } + protected virtual string? MongoDbDatabaseName => null; + + public new virtual async ValueTask DisposeAsync() + { + await base.DisposeAsync(); + } + + public virtual async Task InitializeAsync() + { + Client = CreateClient(); + } + + protected override void ConfigureWebHost(IWebHostBuilder builder) + { + builder.UseSetting("DbProvider", DbProvider); + builder.UseSetting("ConnectionStrings:DefaultConnection", ConnectionString); + + if (MongoDbDatabaseName != null) + { + builder.UseSetting("MongoDbDatabaseName", MongoDbDatabaseName); + } + + builder.ConfigureTestServices(services => + { + // config from Program.cs + }); + } + + protected ScriptRecordDto CreateSampleScriptDto() + { + return new ScriptRecordDto + { + SessionId = Guid.NewGuid(), + Meta = new MetaDto {SchemaVersion = new Version(2, 0)}, + Timestamp = DateTimeOffset.UtcNow, + Username = "testuser", + HostUsername = "hostuser", + RevitBuild = "2024.1", + RevitVersion = "2024", + PyRevitVersion = "4.8.14", + CloneName = "master", + IsDebug = false, + IsConfig = false, + IsExecFromGui = true, + ExecId = Guid.NewGuid().ToString(), + ExecTimestamp = DateTimeOffset.UtcNow, + CommandBundle = "test.extension", + CommandExtension = "test", + CommandName = "Test Command", + CommandUniqueName = "test.command.unique", + DocumentName = "test.rvt", + DocumentPath = @"C:\test.rvt", + ResultCode = 0, + ScriptPath = @"C:\scripts\test.py", + Trace = new TraceInfoDto + { + Message = "test trace message", + Engine = new EngineInfoDto + { + Type = "ironpython", + Version = "2.7.12", + SysPath = ["path1", "path2"], + Configs = "some configs" + } + }, + CommandResults = "success" + }; + } + + protected EventRecordDto CreateSampleEventDto() + { + return new EventRecordDto + { + HandlerId = Guid.NewGuid(), + Meta = new MetaDto {SchemaVersion = new Version(2, 0)}, + EventType = "app-startup", + Status = "success", + Timestamp = DateTimeOffset.UtcNow, + Username = "testuser", + HostUsername = "hostuser", + RevitBuild = "2024.1", + RevitVersion = "2024", + Cancelled = false, + DocumentId = 12345, + DocumentType = "Project", + DocumentTemplate = "template.rte", + DocumentName = "test.rvt", + DocumentPath = "C:\\test.rvt", + ProjectName = "Test Project", + ProjectNum = "123-456", + EventArgs = "some args" + }; + } + } +} \ No newline at end of file diff --git a/tests/Telemetry.Api.IntegrationTests/MongoDbIntegrationTests.cs b/tests/Telemetry.Api.IntegrationTests/MongoDbIntegrationTests.cs new file mode 100644 index 0000000..eafd21a --- /dev/null +++ b/tests/Telemetry.Api.IntegrationTests/MongoDbIntegrationTests.cs @@ -0,0 +1,67 @@ +using Telemetry.Api.Application.DTOs; +using Testcontainers.MongoDb; + +namespace Telemetry.Api.IntegrationTests +{ + public class MongoDbIntegrationTests : BaseIntegrationTest + { + private readonly MongoDbContainer _container = new MongoDbBuilder("mongo:8.2") + .Build(); + + protected override string DbProvider => "mongodb"; + protected override string ConnectionString => _container.GetConnectionString(); + protected override string MongoDbDatabaseName => "telemetry_test"; + + public override async Task InitializeAsync() + { + await _container.StartAsync(); + await base.InitializeAsync(); + } + + public override async ValueTask DisposeAsync() + { + await base.DisposeAsync(); + await _container.StopAsync(); + await _container.DisposeAsync(); + } + + [Test] + public async Task GetStatus_ReturnsOk() + { + // Act + HttpResponseMessage response = await Client.GetAsync("/api/v2/status"); + + // Assert + response.EnsureSuccessStatusCode(); + string content = await response.Content.ReadAsStringAsync(); + await Assert.That(content).Contains("\"status\":\"pass\""); + await Assert.That(content).Contains("MongoDB.EntityFrameworkCore"); + } + + [Test] + public async Task PostScript_ReturnsOk() + { + // Arrange + ScriptRecordDto dto = CreateSampleScriptDto(); + + // Act + HttpResponseMessage response = await Client.PostAsJsonAsync("/api/v2/scripts", dto); + + // Assert + response.EnsureSuccessStatusCode(); + } + + [Test] + public async Task PostEvent_ReturnsOk() + { + // Arrange + EventRecordDto dto = CreateSampleEventDto(); + + // Act + HttpResponseMessage response = await Client.PostAsJsonAsync("/api/v2/events", dto); + + // Assert + response.EnsureSuccessStatusCode(); + } + } +} \ No newline at end of file diff --git a/tests/Telemetry.Api.IntegrationTests/MsSqlIntegrationTests.cs b/tests/Telemetry.Api.IntegrationTests/MsSqlIntegrationTests.cs new file mode 100644 index 0000000..55474c8 --- /dev/null +++ b/tests/Telemetry.Api.IntegrationTests/MsSqlIntegrationTests.cs @@ -0,0 +1,66 @@ +using Telemetry.Api.Application.DTOs; +using Testcontainers.MsSql; + +namespace Telemetry.Api.IntegrationTests +{ + public class MsSqlIntegrationTests : BaseIntegrationTest + { + private readonly MsSqlContainer _container = new MsSqlBuilder("mcr.microsoft.com/mssql/server:2025-latest") + .Build(); + + protected override string DbProvider => "mssql"; + protected override string ConnectionString => _container.GetConnectionString(); + + public override async Task InitializeAsync() + { + await _container.StartAsync(); + await base.InitializeAsync(); + } + + public override async ValueTask DisposeAsync() + { + await base.DisposeAsync(); + await _container.StopAsync(); + await _container.DisposeAsync(); + } + + [Test] + public async Task GetStatus_ReturnsOk() + { + // Act + HttpResponseMessage response = await Client.GetAsync("/api/v2/status"); + + // Assert + response.EnsureSuccessStatusCode(); + string content = await response.Content.ReadAsStringAsync(); + await Assert.That(content).Contains("\"status\":\"pass\""); + await Assert.That(content).Contains("Microsoft.EntityFrameworkCore.SqlServer"); + } + + [Test] + public async Task PostScript_ReturnsOk() + { + // Arrange + ScriptRecordDto dto = CreateSampleScriptDto(); + + // Act + HttpResponseMessage response = await Client.PostAsJsonAsync("/api/v2/scripts", dto); + + // Assert + response.EnsureSuccessStatusCode(); + } + + [Test] + public async Task PostEvent_ReturnsOk() + { + // Arrange + EventRecordDto dto = CreateSampleEventDto(); + + // Act + HttpResponseMessage response = await Client.PostAsJsonAsync("/api/v2/events", dto); + + // Assert + response.EnsureSuccessStatusCode(); + } + } +} \ No newline at end of file diff --git a/tests/Telemetry.Api.IntegrationTests/OracleIntegrationTests.cs b/tests/Telemetry.Api.IntegrationTests/OracleIntegrationTests.cs new file mode 100644 index 0000000..de0dd76 --- /dev/null +++ b/tests/Telemetry.Api.IntegrationTests/OracleIntegrationTests.cs @@ -0,0 +1,66 @@ +using Telemetry.Api.Application.DTOs; +using Testcontainers.Oracle; + +namespace Telemetry.Api.IntegrationTests +{ + public class OracleIntegrationTests : BaseIntegrationTest + { + private readonly OracleContainer _container = new OracleBuilder("gvenzl/oracle-free:23-slim") + .Build(); + + protected override string DbProvider => "oracle"; + protected override string ConnectionString => _container.GetConnectionString().Replace("XEPDB1", "FREEPDB1"); + + public override async Task InitializeAsync() + { + await _container.StartAsync(); + await base.InitializeAsync(); + } + + public override async ValueTask DisposeAsync() + { + await base.DisposeAsync(); + await _container.StopAsync(); + await _container.DisposeAsync(); + } + + [Test] + public async Task GetStatus_ReturnsOk() + { + // Act + HttpResponseMessage response = await Client.GetAsync("/api/v2/status"); + + // Assert + response.EnsureSuccessStatusCode(); + string content = await response.Content.ReadAsStringAsync(); + await Assert.That(content).Contains("\"status\":\"pass\""); + await Assert.That(content).Contains("Oracle.EntityFrameworkCore"); + } + + [Test] + public async Task PostScript_ReturnsOk() + { + // Arrange + ScriptRecordDto dto = CreateSampleScriptDto(); + + // Act + HttpResponseMessage response = await Client.PostAsJsonAsync("/api/v2/scripts", dto); + + // Assert + response.EnsureSuccessStatusCode(); + } + + [Test] + public async Task PostEvent_ReturnsOk() + { + // Arrange + EventRecordDto dto = CreateSampleEventDto(); + + // Act + HttpResponseMessage response = await Client.PostAsJsonAsync("/api/v2/events", dto); + + // Assert + response.EnsureSuccessStatusCode(); + } + } +} \ No newline at end of file diff --git a/tests/Telemetry.Api.IntegrationTests/PostgresIntegrationTests.cs b/tests/Telemetry.Api.IntegrationTests/PostgresIntegrationTests.cs new file mode 100644 index 0000000..0e7b7bd --- /dev/null +++ b/tests/Telemetry.Api.IntegrationTests/PostgresIntegrationTests.cs @@ -0,0 +1,66 @@ +using Telemetry.Api.Application.DTOs; +using Testcontainers.PostgreSql; + +namespace Telemetry.Api.IntegrationTests +{ + public class PostgresIntegrationTests : BaseIntegrationTest + { + private readonly PostgreSqlContainer _container = new PostgreSqlBuilder("postgres:18-alpine") + .Build(); + + protected override string DbProvider => "postgres"; + protected override string ConnectionString => _container.GetConnectionString(); + + public override async Task InitializeAsync() + { + await _container.StartAsync(); + await base.InitializeAsync(); + } + + public override async ValueTask DisposeAsync() + { + await base.DisposeAsync(); + await _container.StopAsync(); + await _container.DisposeAsync(); + } + + [Test] + public async Task GetStatus_ReturnsOk() + { + // Act + HttpResponseMessage response = await Client.GetAsync("/api/v2/status"); + + // Assert + response.EnsureSuccessStatusCode(); + string content = await response.Content.ReadAsStringAsync(); + await Assert.That(content).Contains("\"status\":\"pass\""); + await Assert.That(content).Contains("Npgsql.EntityFrameworkCore.PostgreSQL"); + } + + [Test] + public async Task PostScript_ReturnsOk() + { + // Arrange + ScriptRecordDto dto = CreateSampleScriptDto(); + + // Act + HttpResponseMessage response = await Client.PostAsJsonAsync("/api/v2/scripts", dto); + + // Assert + response.EnsureSuccessStatusCode(); + } + + [Test] + public async Task PostEvent_ReturnsOk() + { + // Arrange + EventRecordDto dto = CreateSampleEventDto(); + + // Act + HttpResponseMessage response = await Client.PostAsJsonAsync("/api/v2/events", dto); + + // Assert + response.EnsureSuccessStatusCode(); + } + } +} \ No newline at end of file diff --git a/tests/Telemetry.Api.IntegrationTests/SqliteIntegrationTests.cs b/tests/Telemetry.Api.IntegrationTests/SqliteIntegrationTests.cs new file mode 100644 index 0000000..12e8bf7 --- /dev/null +++ b/tests/Telemetry.Api.IntegrationTests/SqliteIntegrationTests.cs @@ -0,0 +1,65 @@ +using Telemetry.Api.Application.DTOs; + +namespace Telemetry.Api.IntegrationTests +{ + public class SqliteIntegrationTests : BaseIntegrationTest + { + private readonly string _dbPath = $"telemetry_{Guid.NewGuid()}.db"; + + protected override string DbProvider => "sqlite"; + protected override string ConnectionString => $"Data Source={_dbPath}"; + + public override async Task InitializeAsync() + { + await base.InitializeAsync(); + } + + public override async ValueTask DisposeAsync() + { + await base.DisposeAsync(); + if (File.Exists(_dbPath)) + { + File.Delete(_dbPath); + } + } + + [Test] + public async Task GetStatus_ReturnsOk() + { + // Act + HttpResponseMessage response = await Client.GetAsync("/api/v2/status"); + + // Assert + response.EnsureSuccessStatusCode(); + string content = await response.Content.ReadAsStringAsync(); + await Assert.That(content).Contains("\"status\":\"pass\""); + await Assert.That(content).Contains("Microsoft.EntityFrameworkCore.Sqlite"); + } + + [Test] + public async Task PostScript_ReturnsOk() + { + // Arrange + ScriptRecordDto dto = CreateSampleScriptDto(); + + // Act + HttpResponseMessage response = await Client.PostAsJsonAsync("/api/v2/scripts", dto); + + // Assert + response.EnsureSuccessStatusCode(); + } + + [Test] + public async Task PostEvent_ReturnsOk() + { + // Arrange + EventRecordDto dto = CreateSampleEventDto(); + + // Act + HttpResponseMessage response = await Client.PostAsJsonAsync("/api/v2/events", dto); + + // Assert + response.EnsureSuccessStatusCode(); + } + } +} \ No newline at end of file diff --git a/tests/Telemetry.Api.IntegrationTests/Telemetry.Api.IntegrationTests.csproj b/tests/Telemetry.Api.IntegrationTests/Telemetry.Api.IntegrationTests.csproj new file mode 100644 index 0000000..aee3e7f --- /dev/null +++ b/tests/Telemetry.Api.IntegrationTests/Telemetry.Api.IntegrationTests.csproj @@ -0,0 +1,32 @@ + + + + net10.0 + enable + enable + false + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/Telemetry.Api.UnitTests/Application/Mappings/TelemetryMappingExtensionsTests.cs b/tests/Telemetry.Api.UnitTests/Application/Mappings/TelemetryMappingExtensionsTests.cs new file mode 100644 index 0000000..03f54b7 --- /dev/null +++ b/tests/Telemetry.Api.UnitTests/Application/Mappings/TelemetryMappingExtensionsTests.cs @@ -0,0 +1,306 @@ +using Telemetry.Api.Application.DTOs; +using Telemetry.Api.Application.Mappings; +using Telemetry.Api.Domain.Models; + +namespace Telemetry.Api.UnitTests.Application.Mappings +{ + public class TelemetryMappingExtensionsTests + { + [Test] + public async Task MetaDto_ToModel_ShouldMapCorrectly() + { + // Arrange + MetaDto dto = new() {SchemaVersion = new Version(2, 1)}; + + // Act + MetaRecord model = dto.ToModel(); + + // Assert + await Assert.That(model.SchemaVersion).IsEqualTo(dto.SchemaVersion); + } + + [Test] + public async Task MetaRecord_ToDto_ShouldMapCorrectly() + { + // Arrange + MetaRecord model = new() {SchemaVersion = new Version(2, 1)}; + + // Act + MetaDto dto = model.ToDto(); + + // Assert + await Assert.That(dto.SchemaVersion).IsEqualTo(model.SchemaVersion); + } + + [Test] + public async Task EngineInfoDto_ToModel_ShouldMapCorrectly() + { + // Arrange + EngineInfoDto dto = new() + { + Type = "CPython", Version = "3.8", SysPath = new[] {"path1", "path2"}, Configs = "some config" + }; + + // Act + EngineInfo model = dto.ToModel(); + + // Assert + await Assert.That(model.Type).IsEqualTo(dto.Type); + await Assert.That(model.Version).IsEqualTo(dto.Version); + await Assert.That(model.SysPaths).IsEquivalentTo(dto.SysPath); + await Assert.That(model.Configs).IsEqualTo(dto.Configs); + } + + [Test] + public async Task TraceInfoDto_ToModel_ShouldMapCorrectly() + { + // Arrange + TraceInfoDto dto = new() + { + Message = "Test message", Engine = new EngineInfoDto {Type = "IronPython", Version = "2.7"} + }; + + // Act + TraceInfo model = dto.ToModel(); + + // Assert + await Assert.That(model.Message).IsEqualTo(dto.Message); + await Assert.That(model.Engine.Type).IsEqualTo(dto.Engine.Type); + await Assert.That(model.Engine.Version).IsEqualTo(dto.Engine.Version); + } + + [Test] + public async Task ScriptRecordDto_ToModel_ShouldMapCorrectly() + { + // Arrange + ScriptRecordDto dto = new() + { + SessionId = Guid.NewGuid(), + Meta = new MetaDto {SchemaVersion = new Version(2, 0)}, + Timestamp = DateTimeOffset.Now, + Username = "user", + HostUsername = "host", + RevitBuild = "2024.1", + RevitVersion = "2024", + PyRevitVersion = "4.8.12", + CloneName = "master", + IsDebug = true, + IsConfig = true, + IsExecFromGui = true, + ExecId = "exec-123", + ExecTimestamp = DateTimeOffset.Now.AddSeconds(-10), + CommandBundle = "bundle", + CommandExtension = "ext", + CommandName = "cmd", + CommandUniqueName = "unique.cmd", + DocumentName = "doc", + DocumentPath = "C:/path/to/doc.rvt", + ResultCode = 0, + ScriptPath = "C:/path/to/script.py", + Trace = new TraceInfoDto + { + Message = "trace", Engine = new EngineInfoDto {Type = "python", Version = "3"} + }, + CommandResults = "results" + }; + + // Act + ScriptRecord model = dto.ToModel(); + + // Assert + await Assert.That(model.Id).IsNotEqualTo(Guid.Empty); + await Assert.That(model.SessionId).IsEqualTo(dto.SessionId); + await Assert.That(model.Meta.SchemaVersion).IsEqualTo(dto.Meta.SchemaVersion); + await Assert.That(model.Timestamp).IsEqualTo(dto.Timestamp); + await Assert.That(model.Username).IsEqualTo(dto.Username); + await Assert.That(model.HostUsername).IsEqualTo(dto.HostUsername); + await Assert.That(model.RevitBuild).IsEqualTo(dto.RevitBuild); + await Assert.That(model.RevitVersion).IsEqualTo(dto.RevitVersion); + await Assert.That(model.PyRevitVersion).IsEqualTo(dto.PyRevitVersion); + await Assert.That(model.CloneName).IsEqualTo(dto.CloneName); + await Assert.That(model.IsDebug).IsEqualTo(dto.IsDebug); + await Assert.That(model.IsConfig).IsEqualTo(dto.IsConfig); + await Assert.That(model.IsExecFromGui).IsEqualTo(dto.IsExecFromGui); + await Assert.That(model.ExecId).IsEqualTo(dto.ExecId); + await Assert.That(model.ExecTimestamp).IsEqualTo(dto.ExecTimestamp); + await Assert.That(model.CommandBundle).IsEqualTo(dto.CommandBundle); + await Assert.That(model.CommandExtension).IsEqualTo(dto.CommandExtension); + await Assert.That(model.CommandName).IsEqualTo(dto.CommandName); + await Assert.That(model.CommandUniqueName).IsEqualTo(dto.CommandUniqueName); + await Assert.That(model.DocumentName).IsEqualTo(dto.DocumentName); + await Assert.That(model.DocumentPath).IsEqualTo(dto.DocumentPath); + await Assert.That(model.ResultCode).IsEqualTo(dto.ResultCode); + await Assert.That(model.ScriptPath).IsEqualTo(dto.ScriptPath); + await Assert.That(model.Trace.Message).IsEqualTo(dto.Trace.Message); + await Assert.That(model.CommandResults).IsEqualTo(dto.CommandResults); + } + + [Test] + public async Task ScriptRecord_ToDto_ShouldMapCorrectly() + { + // Arrange + ScriptRecord model = new() + { + Id = Guid.NewGuid(), + SessionId = Guid.NewGuid(), + Meta = new MetaRecord {SchemaVersion = new Version(2, 0)}, + Timestamp = DateTimeOffset.Now, + Username = "user", + HostUsername = "host", + RevitBuild = "2024.1", + RevitVersion = "2024", + PyRevitVersion = "4.8.12", + CloneName = "master", + IsDebug = true, + IsConfig = true, + IsExecFromGui = true, + ExecId = "exec-123", + ExecTimestamp = DateTimeOffset.Now.AddSeconds(-10), + CommandBundle = "bundle", + CommandExtension = "ext", + CommandName = "cmd", + CommandUniqueName = "unique.cmd", + DocumentName = "doc", + DocumentPath = "C:/path/to/doc.rvt", + ResultCode = 0, + ScriptPath = "C:/path/to/script.py", + Trace = new TraceInfo + { + Message = "trace", Engine = new EngineInfo {Type = "python", Version = "3"} + }, + CommandResults = "results" + }; + + // Act + ScriptRecordDto dto = model.ToDto(); + + // Assert + await Assert.That(dto.SessionId).IsEqualTo(model.SessionId); + await Assert.That(dto.Meta.SchemaVersion).IsEqualTo(model.Meta.SchemaVersion); + await Assert.That(dto.Timestamp).IsEqualTo(model.Timestamp); + await Assert.That(dto.Username).IsEqualTo(model.Username); + await Assert.That(dto.HostUsername).IsEqualTo(model.HostUsername); + await Assert.That(dto.RevitBuild).IsEqualTo(model.RevitBuild); + await Assert.That(dto.RevitVersion).IsEqualTo(model.RevitVersion); + await Assert.That(dto.PyRevitVersion).IsEqualTo(model.PyRevitVersion); + await Assert.That(dto.CloneName).IsEqualTo(model.CloneName); + await Assert.That(dto.IsDebug).IsEqualTo(model.IsDebug); + await Assert.That(dto.IsConfig).IsEqualTo(model.IsConfig); + await Assert.That(dto.IsExecFromGui).IsEqualTo(model.IsExecFromGui); + await Assert.That(dto.ExecId).IsEqualTo(model.ExecId); + await Assert.That(dto.ExecTimestamp).IsEqualTo(model.ExecTimestamp); + await Assert.That(dto.CommandBundle).IsEqualTo(model.CommandBundle); + await Assert.That(dto.CommandExtension).IsEqualTo(model.CommandExtension); + await Assert.That(dto.CommandName).IsEqualTo(model.CommandName); + await Assert.That(dto.CommandUniqueName).IsEqualTo(model.CommandUniqueName); + await Assert.That(dto.DocumentName).IsEqualTo(model.DocumentName); + await Assert.That(dto.DocumentPath).IsEqualTo(model.DocumentPath); + await Assert.That(dto.ResultCode).IsEqualTo(model.ResultCode); + await Assert.That(dto.ScriptPath).IsEqualTo(model.ScriptPath); + await Assert.That(dto.Trace.Message).IsEqualTo(model.Trace.Message); + await Assert.That(dto.CommandResults).IsEqualTo(model.CommandResults); + } + + [Test] + public async Task EventRecordDto_ToModel_ShouldMapCorrectly() + { + // Arrange + EventRecordDto dto = new() + { + HandlerId = Guid.NewGuid(), + Meta = new MetaDto {SchemaVersion = new Version(2, 0)}, + EventType = "DocOpened", + Status = "Success", + Timestamp = DateTimeOffset.Now, + Username = "user", + HostUsername = "host", + RevitBuild = "2024.1", + RevitVersion = "2024", + Cancelled = false, + DocumentId = 1, + DocumentType = "Project", + DocumentTemplate = "template", + DocumentName = "doc", + DocumentPath = "C:/path/to/doc.rvt", + ProjectName = "project", + ProjectNum = "123", + EventArgs = "args" + }; + + // Act + EventRecord model = dto.ToModel(); + + // Assert + await Assert.That(model.Id).IsNotEqualTo(Guid.Empty); + await Assert.That(model.HandlerId).IsEqualTo(dto.HandlerId); + await Assert.That(model.Meta.SchemaVersion).IsEqualTo(dto.Meta.SchemaVersion); + await Assert.That(model.EventType).IsEqualTo(dto.EventType); + await Assert.That(model.Status).IsEqualTo(dto.Status); + await Assert.That(model.Timestamp).IsEqualTo(dto.Timestamp); + await Assert.That(model.Username).IsEqualTo(dto.Username); + await Assert.That(model.HostUsername).IsEqualTo(dto.HostUsername); + await Assert.That(model.RevitBuild).IsEqualTo(dto.RevitBuild); + await Assert.That(model.RevitVersion).IsEqualTo(dto.RevitVersion); + await Assert.That(model.Cancelled).IsEqualTo(dto.Cancelled); + await Assert.That(model.DocumentId).IsEqualTo(dto.DocumentId); + await Assert.That(model.DocumentType).IsEqualTo(dto.DocumentType); + await Assert.That(model.DocumentTemplate).IsEqualTo(dto.DocumentTemplate); + await Assert.That(model.DocumentName).IsEqualTo(dto.DocumentName); + await Assert.That(model.DocumentPath).IsEqualTo(dto.DocumentPath); + await Assert.That(model.ProjectName).IsEqualTo(dto.ProjectName); + await Assert.That(model.ProjectNum).IsEqualTo(dto.ProjectNum); + await Assert.That(model.EventArgs).IsEqualTo(dto.EventArgs); + } + + [Test] + public async Task EventRecord_ToDto_ShouldMapCorrectly() + { + // Arrange + EventRecord model = new() + { + Id = Guid.NewGuid(), + HandlerId = Guid.NewGuid(), + Meta = new MetaRecord {SchemaVersion = new Version(2, 0)}, + EventType = "DocOpened", + Status = "Success", + Timestamp = DateTimeOffset.Now, + Username = "user", + HostUsername = "host", + RevitBuild = "2024.1", + RevitVersion = "2024", + Cancelled = false, + DocumentId = 1, + DocumentType = "Project", + DocumentTemplate = "template", + DocumentName = "doc", + DocumentPath = "C:/path/to/doc.rvt", + ProjectName = "project", + ProjectNum = "123", + EventArgs = "args" + }; + + // Act + EventRecordDto dto = model.ToDto(); + + // Assert + await Assert.That(dto.HandlerId).IsEqualTo(model.HandlerId); + await Assert.That(dto.Meta.SchemaVersion).IsEqualTo(model.Meta.SchemaVersion); + await Assert.That(dto.EventType).IsEqualTo(model.EventType); + await Assert.That(dto.Status).IsEqualTo(model.Status); + await Assert.That(dto.Timestamp).IsEqualTo(model.Timestamp); + await Assert.That(dto.Username).IsEqualTo(model.Username); + await Assert.That(dto.HostUsername).IsEqualTo(model.HostUsername); + await Assert.That(dto.RevitBuild).IsEqualTo(model.RevitBuild); + await Assert.That(dto.RevitVersion).IsEqualTo(model.RevitVersion); + await Assert.That(dto.Cancelled).IsEqualTo(model.Cancelled); + await Assert.That(dto.DocumentId).IsEqualTo(model.DocumentId); + await Assert.That(dto.DocumentType).IsEqualTo(model.DocumentType); + await Assert.That(dto.DocumentTemplate).IsEqualTo(model.DocumentTemplate); + await Assert.That(dto.DocumentName).IsEqualTo(model.DocumentName); + await Assert.That(dto.DocumentPath).IsEqualTo(model.DocumentPath); + await Assert.That(dto.ProjectName).IsEqualTo(model.ProjectName); + await Assert.That(dto.ProjectNum).IsEqualTo(model.ProjectNum); + await Assert.That(dto.EventArgs).IsEqualTo(model.EventArgs); + } + } +} \ No newline at end of file diff --git a/tests/Telemetry.Api.UnitTests/Telemetry.Api.UnitTests.csproj b/tests/Telemetry.Api.UnitTests/Telemetry.Api.UnitTests.csproj new file mode 100644 index 0000000..a44496a --- /dev/null +++ b/tests/Telemetry.Api.UnitTests/Telemetry.Api.UnitTests.csproj @@ -0,0 +1,25 @@ + + + + net10.0 + enable + enable + false + Exe + + + + + + + + + + + + + + + + + diff --git a/tests/Telemetry.Api.UnitTests/Web/Controllers/TelemetryControllerTests.cs b/tests/Telemetry.Api.UnitTests/Web/Controllers/TelemetryControllerTests.cs new file mode 100644 index 0000000..0a2a36d --- /dev/null +++ b/tests/Telemetry.Api.UnitTests/Web/Controllers/TelemetryControllerTests.cs @@ -0,0 +1,150 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; +using Moq; +using Telemetry.Api.Application.DTOs; +using Telemetry.Api.Application.Interfaces; +using Telemetry.Api.Domain.Models; +using Telemetry.Api.Web.Controllers; +using System.Text.Json; + +namespace Telemetry.Api.UnitTests.Web.Controllers +{ + public class TelemetryControllerTests + { + private readonly TelemetryController _controller; + private readonly Mock _mockContext; + private readonly Mock> _mockLogger; + private readonly Mock _mockServiceInfo; + + public TelemetryControllerTests() + { + _mockContext = new Mock(); + _mockLogger = new Mock>(); + _mockServiceInfo = new Mock(); + _controller = new TelemetryController(_mockContext.Object, _mockLogger.Object, _mockServiceInfo.Object); + + // Mock HttpContext + DefaultHttpContext httpContext = new(); + _controller.ControllerContext = new ControllerContext {HttpContext = httpContext}; + } + + [Test] + public async Task PostScript_ShouldReturnOk_WhenSuccessful() + { + // Arrange + ScriptRecordDto dto = CreateValidScriptRecordDto(); + Mock> mockDbSet = new(); + _mockContext.Setup(c => c.ScriptRecords).Returns(mockDbSet.Object); + + // Act + IActionResult result = await _controller.PostScript(dto); + + // Assert + await Assert.That(result).IsTypeOf(); + _mockContext.Verify(c => c.ScriptRecords.Add(It.IsAny()), Times.Once); + _mockContext.Verify(c => c.SaveChangesAsync(It.IsAny()), Times.Once); + } + + [Test] + public async Task PostEvent_ShouldReturnOk_WhenSuccessful() + { + // Arrange + EventRecordDto dto = CreateValidEventRecordDto(); + Mock> mockDbSet = new(); + _mockContext.Setup(c => c.EventRecords).Returns(mockDbSet.Object); + + // Act + IActionResult result = await _controller.PostEvent(dto); + + // Assert + await Assert.That(result).IsTypeOf(); + _mockContext.Verify(c => c.EventRecords.Add(It.IsAny()), Times.Once); + _mockContext.Verify(c => c.SaveChangesAsync(It.IsAny()), Times.Once); + } + + [Test] + public async Task GetStatus_ShouldReturnOk_WhenDatabaseConnected() + { + // Arrange + Guid serviceId = Guid.NewGuid(); + _mockContext.Setup(c => c.CanConnectAsync(It.IsAny())).ReturnsAsync(true); + _mockContext.Setup(c => c.GetDbProvider()).Returns("postgres"); + _mockContext.Setup(c => c.GetDbVersionAsync(It.IsAny())).ReturnsAsync("15.0"); + _mockServiceInfo.Setup(s => s.ServiceId).Returns(serviceId); + + // Act + IActionResult result = await _controller.GetStatus(); + + // Assert + OkObjectResult okResult = (OkObjectResult)result; + await Assert.That(okResult).IsTypeOf(); + + // Use reflection or JSON serialization to check anonymous type properties + string statusJson = JsonSerializer.Serialize(okResult.Value); + using JsonDocument doc = JsonDocument.Parse(statusJson); + await Assert.That(doc.RootElement.GetProperty("status").GetString()).IsEqualTo("pass"); + await Assert.That(doc.RootElement.GetProperty("serviceid").GetGuid()).IsEqualTo(serviceId); + } + + private ScriptRecordDto CreateValidScriptRecordDto() + { + return new ScriptRecordDto() + { + SessionId = Guid.NewGuid(), + Meta = new MetaDto() {SchemaVersion = new Version(2, 0)}, + Timestamp = DateTimeOffset.Now, + Username = "user", + HostUsername = "host", + RevitBuild = "2024.1", + RevitVersion = "2024", + PyRevitVersion = "4.8.12", + CloneName = "master", + IsDebug = true, + IsConfig = true, + IsExecFromGui = true, + ExecId = "exec-123", + ExecTimestamp = DateTimeOffset.Now.AddSeconds(-10), + CommandBundle = "bundle", + CommandExtension = "ext", + CommandName = "cmd", + CommandUniqueName = "unique.cmd", + DocumentName = "doc", + DocumentPath = "C:/path/to/doc.rvt", + ResultCode = 0, + ScriptPath = "C:/path/to/script.py", + Trace = new TraceInfoDto() + { + Message = "trace", Engine = new EngineInfoDto() {Type = "python", Version = "3"} + }, + CommandResults = "results" + }; + } + + private EventRecordDto CreateValidEventRecordDto() + { + return new EventRecordDto() + { + HandlerId = Guid.NewGuid(), + Meta = new MetaDto() {SchemaVersion = new Version(2, 0)}, + EventType = "DocOpened", + Status = "Success", + Timestamp = DateTimeOffset.Now, + Username = "user", + HostUsername = "host", + RevitBuild = "2024.1", + RevitVersion = "2024", + Cancelled = false, + DocumentId = 1, + DocumentType = "Project", + DocumentTemplate = "template", + DocumentName = "doc", + DocumentPath = "C:/path/to/doc.rvt", + ProjectName = "project", + ProjectNum = "123", + EventArgs = "args" + }; + } + } +} \ No newline at end of file From 7d56de4e032a1f7ecbb1945a7bafcec4ff29ea94 Mon Sep 17 00:00:00 2001 From: dosymep Date: Mon, 30 Mar 2026 22:12:51 +0600 Subject: [PATCH 02/31] change multiline symbol --- .github/workflows/build.yml | 2 +- .github/workflows/release.yml | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5108702..f7d2c7c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -23,7 +23,7 @@ jobs: run: dotnet restore - name: Build - run: >- + run: | dotnet build "./src/Telemetry.Api/Telemetry.Api.csproj" -c $BUILD_CONFIGURATION -o $BUILD_PATH dotnet build "./src/Telemetry.Migrations.Oracle/Telemetry.Migrations.Oracle.csproj" -c $BUILD_CONFIGURATION -o $BUILD_PATH dotnet build "./src/Telemetry.Migrations.Postgres/Telemetry.Migrations.Postgres.csproj" -c $BUILD_CONFIGURATION -o $BUILD_PATH diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index fd7fb94..9f899a3 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -28,7 +28,7 @@ jobs: run: dotnet restore - name: Build - run: >- + run: | dotnet build "./src/Telemetry.Api/Telemetry.Api.csproj" -c $BUILD_CONFIGURATION -o $BUILD_PATH dotnet build "./src/Telemetry.Migrations.Oracle/Telemetry.Migrations.Oracle.csproj" -c $BUILD_CONFIGURATION -o $BUILD_PATH dotnet build "./src/Telemetry.Migrations.Postgres/Telemetry.Migrations.Postgres.csproj" -c $BUILD_CONFIGURATION -o $BUILD_PATH @@ -36,7 +36,7 @@ jobs: dotnet build "./src/Telemetry.Migrations.SqlServer/Telemetry.Migrations.SqlServer.csproj" -c $BUILD_CONFIGURATION -o $BUILD_PATH - name: Publish - run: >- + run: | dotnet publish "./src/Telemetry.Api/Telemetry.Api.csproj" -c $BUILD_CONFIGURATION -o $PUBLISH_PATH dotnet publish "./src/Telemetry.Migrations.Oracle/Telemetry.Migrations.Oracle.csproj" -c $BUILD_CONFIGURATION -o $MIGRATIONS_PATH/oracle dotnet publish "./src/Telemetry.Migrations.Postgres/Telemetry.Migrations.Postgres.csproj" -c $BUILD_CONFIGURATION -o $MIGRATIONS_PATH/postgres @@ -47,7 +47,7 @@ jobs: uses: actions/upload-artifact@v7 with: name: publish - path: >- + path: | ${{ env.BUILD_PATH }}/*.* ${{ env.MIGRATIONS_PATH }}/oracle/Telemetry.Migrations.Oracle.dll ${{ env.MIGRATIONS_PATH }}/postgres/Telemetry.Migrations.Postgres.dll @@ -64,7 +64,7 @@ jobs: body: dont forget fill changelog tag_name: ${{ env.VERSION }} name: pyrevit-telemetry ${{ env.VERSION }} - files: >- + files: | ${{ env.BUILD_PATH }}/*.* ${{ env.MIGRATIONS_PATH }}/oracle/Telemetry.Migrations.Oracle.dll ${{ env.MIGRATIONS_PATH }}/postgres/Telemetry.Migrations.Postgres.dll From 73578a3bd9f532d32892b507a4d02ebad388fe84 Mon Sep 17 00:00:00 2001 From: dosymep Date: Mon, 30 Mar 2026 22:14:48 +0600 Subject: [PATCH 03/31] fix build path env variable --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f7d2c7c..8dbd623 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -35,7 +35,7 @@ jobs: uses: actions/upload-artifact@v7 with: name: build - path: ${BUILD_PATH} + path: ${{ env.BUILD_PATH }} docker-publish: runs-on: ubuntu-latest From c12d63702d759147687ff7e7e4b89cb1571de987 Mon Sep 17 00:00:00 2001 From: dosymep Date: Mon, 30 Mar 2026 22:15:07 +0600 Subject: [PATCH 04/31] fix tests job name --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 3a0e801..46b7062 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -9,7 +9,7 @@ env: BUILD_CONFIGURATION: Debug jobs: - test: + tests: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 From e33b6fcea22736aaf2a084e02d67f092f87e4a33 Mon Sep 17 00:00:00 2001 From: dosymep Date: Mon, 30 Mar 2026 22:19:07 +0600 Subject: [PATCH 05/31] fix tests reports path --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 46b7062..016f105 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -38,4 +38,4 @@ jobs: uses: actions/upload-artifact@v7 with: name: test-results - path: '**/TestResults/*.*' + path: '**/*-report.html' From c4d0f34f187d79775365ac388426db818392f1f6 Mon Sep 17 00:00:00 2001 From: dosymep Date: Thu, 2 Apr 2026 19:47:23 +0600 Subject: [PATCH 06/31] add checkout step to release and build workflows --- .github/workflows/build.yml | 1 + .github/workflows/release.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8dbd623..504395a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -40,6 +40,7 @@ jobs: docker-publish: runs-on: ubuntu-latest steps: + - uses: actions/checkout@v6 - name: Generate version run: echo "VERSION=2.0.0.${{ github.run_number }}-alpha" >> $GITHUB_ENV diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9f899a3..2d92715 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -74,6 +74,7 @@ jobs: docker-publish: runs-on: ubuntu-latest steps: + - uses: actions/checkout@v6 - name: Generate version run: echo "VERSION=2.0.0.${{ github.run_number }}" >> $GITHUB_ENV From 342ab9ee757064c69eeeba695d0114156a876b7e Mon Sep 17 00:00:00 2001 From: dosymep Date: Thu, 2 Apr 2026 19:52:49 +0600 Subject: [PATCH 07/31] update Docker build context and specify Dockerfiles in workflows --- .github/workflows/build.yml | 13 +++++++++++-- .github/workflows/release.yml | 6 ++++-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 504395a..0e81b91 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -41,7 +41,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - - name: Generate version + - name: Generate a version run: echo "VERSION=2.0.0.${{ github.run_number }}-alpha" >> $GITHUB_ENV - name: Login to Docker Hub @@ -55,10 +55,19 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@v4 + + - name: Build and push + uses: docker/build-push-action@v7 + with: + push: true + context: . + file: src/Telemetry.Api/Dockerfile + tags: pyrevitlabs/pyrevit-telemetry:alpha - name: Build and push uses: docker/build-push-action@v7 with: push: true - context: src/Telemetry.Api + context: . + file: src/Telemetry.Api/Dockerfile tags: pyrevitlabs/pyrevit-telemetry:${{ env.VERSION }} \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2d92715..983376e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -94,12 +94,14 @@ jobs: uses: docker/build-push-action@v7 with: push: true - context: src/Telemetry.Api + context: . + file: src/Telemetry.Api/Dockerfile tags: pyrevitlabs/pyrevit-telemetry:latest - name: Build and push uses: docker/build-push-action@v7 with: push: true - context: src/Telemetry.Api + context: . + file: src/Telemetry.Api/Dockerfile tags: pyrevitlabs/pyrevit-telemetry:${{ env.VERSION }} \ No newline at end of file From 410bc1554c6bbba5b20f6dc35f2100489a571a4e Mon Sep 17 00:00:00 2001 From: dosymep Date: Thu, 2 Apr 2026 19:56:05 +0600 Subject: [PATCH 08/31] change HTTP logging configuration to Program.cs --- src/Telemetry.Api/Program.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Telemetry.Api/Program.cs b/src/Telemetry.Api/Program.cs index f51fdc4..1282ad4 100644 --- a/src/Telemetry.Api/Program.cs +++ b/src/Telemetry.Api/Program.cs @@ -23,7 +23,11 @@ builder.Services.AddHttpLogging(logging => { - logging.LoggingFields = HttpLoggingFields.All; + logging.LoggingFields = HttpLoggingFields.RequestMethod | + HttpLoggingFields.RequestPath | + HttpLoggingFields.ResponseStatusCode | + HttpLoggingFields.Duration; + logging.RequestBodyLogLimit = 4096; logging.ResponseBodyLogLimit = 4096; }); From 8e0cf2ebbac0b341d508cd4be724c286478c4e15 Mon Sep 17 00:00:00 2001 From: dosymep Date: Thu, 2 Apr 2026 20:03:41 +0600 Subject: [PATCH 09/31] remove ExceptionHandlingMiddleware and logic from Program.cs --- src/Telemetry.Api/Program.cs | 8 +----- .../Middleware/ExceptionHandlingMiddleware.cs | 27 ------------------- 2 files changed, 1 insertion(+), 34 deletions(-) delete mode 100644 src/Telemetry.Api/Web/Middleware/ExceptionHandlingMiddleware.cs diff --git a/src/Telemetry.Api/Program.cs b/src/Telemetry.Api/Program.cs index 1282ad4..5174193 100644 --- a/src/Telemetry.Api/Program.cs +++ b/src/Telemetry.Api/Program.cs @@ -6,7 +6,6 @@ using Telemetry.Api.Application.Interfaces; using Telemetry.Api.Application.Services; using Telemetry.Api.Infrastructure.Persistence; -using Telemetry.Api.Web.Middleware; using Serilog; using System.Reflection; using System.Runtime.Loader; @@ -86,9 +85,7 @@ Log.Information("Using MongoDB database"); break; default: - options.UseInMemoryDatabase("TelemetryDb"); - Log.Information("Using In a Memory database"); - break; + throw new NotSupportedException($"Provider {dbProvider} is not supported."); } }); @@ -135,8 +132,6 @@ WebApplication app = builder.Build(); -app.UseMiddleware(); - if (app.Environment.IsDevelopment()) { app.MapOpenApi(); @@ -145,7 +140,6 @@ { c.SwaggerEndpoint("/swagger/v2/swagger.json", "pyRevit Telemetry API v2"); }); - app.UseDeveloperExceptionPage(); } app.UseRouting(); diff --git a/src/Telemetry.Api/Web/Middleware/ExceptionHandlingMiddleware.cs b/src/Telemetry.Api/Web/Middleware/ExceptionHandlingMiddleware.cs deleted file mode 100644 index c8f9754..0000000 --- a/src/Telemetry.Api/Web/Middleware/ExceptionHandlingMiddleware.cs +++ /dev/null @@ -1,27 +0,0 @@ -namespace Telemetry.Api.Web.Middleware -{ - internal class ExceptionHandlingMiddleware - { - private readonly ILogger _logger; - private readonly RequestDelegate _next; - - public ExceptionHandlingMiddleware(RequestDelegate next, ILogger logger) - { - _next = next; - _logger = logger; - } - - public async Task Invoke(HttpContext context) - { - try - { - await _next(context); - } - catch (Exception ex) - { - _logger.LogError(ex, "Unhandled exception"); - context.Response.StatusCode = 500; - } - } - } -} \ No newline at end of file From e7a0dafab6620eb01147b2eee77299c1699767b5 Mon Sep 17 00:00:00 2001 From: dosymep Date: Thu, 2 Apr 2026 20:04:36 +0600 Subject: [PATCH 10/31] remove Log.CloseAndFlush() from Program.cs --- src/Telemetry.Api/Program.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Telemetry.Api/Program.cs b/src/Telemetry.Api/Program.cs index 5174193..3273f24 100644 --- a/src/Telemetry.Api/Program.cs +++ b/src/Telemetry.Api/Program.cs @@ -168,10 +168,6 @@ Log.Fatal(ex, "Migration terminated unexpectedly"); throw; } -finally -{ - Log.CloseAndFlush(); -} try { From 32439c522533b2155cc8c3ee01d8e945919fb4ff Mon Sep 17 00:00:00 2001 From: dosymep Date: Thu, 2 Apr 2026 20:06:51 +0600 Subject: [PATCH 11/31] add Cancellable property mapping to ApplicationDbContext --- .../Infrastructure/Persistence/ApplicationDbContext.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Telemetry.Api/Infrastructure/Persistence/ApplicationDbContext.cs b/src/Telemetry.Api/Infrastructure/Persistence/ApplicationDbContext.cs index 9183320..de9398d 100644 --- a/src/Telemetry.Api/Infrastructure/Persistence/ApplicationDbContext.cs +++ b/src/Telemetry.Api/Infrastructure/Persistence/ApplicationDbContext.cs @@ -188,6 +188,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) entity.Property(e => e.RevitBuild).HasColumnName("revitbuild"); entity.Property(e => e.RevitVersion).HasColumnName("revit"); entity.Property(e => e.Cancelled).HasColumnName("cancelled"); + entity.Property(e => e.Cancellable).HasColumnName("cancellable"); entity.Property(e => e.DocumentId).HasColumnName("docid"); entity.Property(e => e.DocumentType).HasColumnName("doctype"); entity.Property(e => e.DocumentTemplate).HasColumnName("doctemplate"); From 395dc5925da4e05220772baf95b7107b39b91f57 Mon Sep 17 00:00:00 2001 From: dosymep Date: Thu, 2 Apr 2026 20:11:21 +0600 Subject: [PATCH 12/31] remove Microsoft.AspNetCore.Mvc.Core package from tests project and central props --- Directory.Packages.props | 1 - tests/Telemetry.Api.UnitTests/Telemetry.Api.UnitTests.csproj | 1 - 2 files changed, 2 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 7d0e493..46370ff 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -26,7 +26,6 @@ - diff --git a/tests/Telemetry.Api.UnitTests/Telemetry.Api.UnitTests.csproj b/tests/Telemetry.Api.UnitTests/Telemetry.Api.UnitTests.csproj index a44496a..f163c25 100644 --- a/tests/Telemetry.Api.UnitTests/Telemetry.Api.UnitTests.csproj +++ b/tests/Telemetry.Api.UnitTests/Telemetry.Api.UnitTests.csproj @@ -11,7 +11,6 @@ - From 927558221c3d875dbcec06da1e2ceecb62df027f Mon Sep 17 00:00:00 2001 From: dosymep Date: Thu, 2 Apr 2026 20:14:27 +0600 Subject: [PATCH 13/31] use cloning for SchemaVersion in TelemetryMappingExtensions --- .../Application/Mappings/TelemetryMappingExtensions.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Telemetry.Api/Application/Mappings/TelemetryMappingExtensions.cs b/src/Telemetry.Api/Application/Mappings/TelemetryMappingExtensions.cs index 7a8326f..752f9fe 100644 --- a/src/Telemetry.Api/Application/Mappings/TelemetryMappingExtensions.cs +++ b/src/Telemetry.Api/Application/Mappings/TelemetryMappingExtensions.cs @@ -15,7 +15,7 @@ public static class TelemetryMappingExtensions /// A new instance of the model object created from the source. public static MetaRecord ToModel(this MetaDto dto) { - return new MetaRecord {SchemaVersion = new Version(dto.SchemaVersion.Major, dto.SchemaVersion.Minor)}; + return new MetaRecord {SchemaVersion = (Version)dto.SchemaVersion.Clone()}; } /// @@ -25,7 +25,8 @@ public static MetaRecord ToModel(this MetaDto dto) /// A new instance of the data transfer object (DTO) created from the source. public static MetaDto ToDto(this MetaRecord model) { - return new MetaDto {SchemaVersion = new Version(model.SchemaVersion.Major, model.SchemaVersion.Minor)}; + + return new MetaDto {SchemaVersion = (Version)model.SchemaVersion.Clone()}; } /// From 6f1c82723b18d85d5f9920dd595fc659b39c42a7 Mon Sep 17 00:00:00 2001 From: dosymep Date: Thu, 2 Apr 2026 20:17:07 +0600 Subject: [PATCH 14/31] add migration cancellable --- ...402141604_AddCancellableOracle.Designer.cs | 272 ++++++++++++++++++ .../20260402141604_AddCancellableOracle.cs | 28 ++ .../ApplicationDbContextModelSnapshot.cs | 3 +- ...2141612_AddCancellablePostgres.Designer.cs | 272 ++++++++++++++++++ .../20260402141612_AddCancellablePostgres.cs | 28 ++ .../ApplicationDbContextModelSnapshot.cs | 3 +- ...141635_AddCancellableSqlServer.Designer.cs | 272 ++++++++++++++++++ .../20260402141635_AddCancellableSqlServer.cs | 28 ++ .../ApplicationDbContextModelSnapshot.cs | 3 +- ...402141622_AddCancellableSqlite.Designer.cs | 267 +++++++++++++++++ .../20260402141622_AddCancellableSqlite.cs | 28 ++ .../ApplicationDbContextModelSnapshot.cs | 3 +- 12 files changed, 1203 insertions(+), 4 deletions(-) create mode 100644 src/Telemetry.Migrations.Oracle/Migrations/20260402141604_AddCancellableOracle.Designer.cs create mode 100644 src/Telemetry.Migrations.Oracle/Migrations/20260402141604_AddCancellableOracle.cs create mode 100644 src/Telemetry.Migrations.Postgres/Migrations/20260402141612_AddCancellablePostgres.Designer.cs create mode 100644 src/Telemetry.Migrations.Postgres/Migrations/20260402141612_AddCancellablePostgres.cs create mode 100644 src/Telemetry.Migrations.SqlServer/Migrations/20260402141635_AddCancellableSqlServer.Designer.cs create mode 100644 src/Telemetry.Migrations.SqlServer/Migrations/20260402141635_AddCancellableSqlServer.cs create mode 100644 src/Telemetry.Migrations.Sqlite/Migrations/20260402141622_AddCancellableSqlite.Designer.cs create mode 100644 src/Telemetry.Migrations.Sqlite/Migrations/20260402141622_AddCancellableSqlite.cs diff --git a/src/Telemetry.Migrations.Oracle/Migrations/20260402141604_AddCancellableOracle.Designer.cs b/src/Telemetry.Migrations.Oracle/Migrations/20260402141604_AddCancellableOracle.Designer.cs new file mode 100644 index 0000000..6622f86 --- /dev/null +++ b/src/Telemetry.Migrations.Oracle/Migrations/20260402141604_AddCancellableOracle.Designer.cs @@ -0,0 +1,272 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Oracle.EntityFrameworkCore.Metadata; +using Telemetry.Api.Infrastructure.Persistence; + +#nullable disable + +namespace Telemetry.Migrations.Oracle.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20260402141604_AddCancellableOracle")] + partial class AddCancellableOracle + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "10.0.5") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + OracleModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Telemetry.Api.Domain.Models.EventRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("RAW(16)") + .HasColumnName("id"); + + b.Property("Cancellable") + .HasColumnType("BOOLEAN") + .HasColumnName("cancellable"); + + b.Property("Cancelled") + .HasColumnType("BOOLEAN") + .HasColumnName("cancelled"); + + b.Property("DocumentId") + .HasColumnType("NUMBER(10)") + .HasColumnName("docid"); + + b.Property("DocumentName") + .HasMaxLength(250) + .HasColumnType("NVARCHAR2(250)") + .HasColumnName("docname"); + + b.Property("DocumentPath") + .HasMaxLength(1024) + .HasColumnType("NVARCHAR2(1024)") + .HasColumnName("docpath"); + + b.Property("DocumentTemplate") + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("doctemplate"); + + b.Property("DocumentType") + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("doctype"); + + b.Property("EventArgs") + .HasMaxLength(8000) + .HasColumnType("NCLOB") + .HasColumnName("args"); + + b.Property("EventType") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("type"); + + b.Property("HandlerId") + .HasColumnType("RAW(16)") + .HasColumnName("handler_id"); + + b.Property("HostUsername") + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("host_user"); + + b.Property("Meta") + .IsRequired() + .HasColumnType("NVARCHAR2(2000)") + .HasColumnName("meta"); + + b.Property("ProjectName") + .HasMaxLength(250) + .HasColumnType("NVARCHAR2(250)") + .HasColumnName("projectname"); + + b.Property("ProjectNum") + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("projectnum"); + + b.Property("RevitBuild") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("revitbuild"); + + b.Property("RevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("revit"); + + b.Property("Status") + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("status"); + + b.Property("Timestamp") + .HasColumnType("TIMESTAMP(7) WITH TIME ZONE") + .HasColumnName("timestamp"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("username"); + + b.HasKey("Id"); + + b.ToTable("event_record", (string)null); + }); + + modelBuilder.Entity("Telemetry.Api.Domain.Models.ScriptRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("RAW(16)") + .HasColumnName("id"); + + b.Property("CloneName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("clone"); + + b.Property("CommandBundle") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("NVARCHAR2(250)") + .HasColumnName("commandbundle"); + + b.Property("CommandExtension") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("NVARCHAR2(250)") + .HasColumnName("commandextension"); + + b.Property("CommandName") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("NVARCHAR2(250)") + .HasColumnName("commandname"); + + b.Property("CommandResults") + .HasMaxLength(8000) + .HasColumnType("NCLOB") + .HasColumnName("commandresults"); + + b.Property("CommandUniqueName") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("NVARCHAR2(500)") + .HasColumnName("commanduniquename"); + + b.Property("DocumentName") + .HasMaxLength(250) + .HasColumnType("NVARCHAR2(250)") + .HasColumnName("docname"); + + b.Property("DocumentPath") + .HasMaxLength(1024) + .HasColumnType("NVARCHAR2(1024)") + .HasColumnName("docpath"); + + b.Property("ExecId") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("exec_id"); + + b.Property("ExecTimestamp") + .HasColumnType("TIMESTAMP(7) WITH TIME ZONE") + .HasColumnName("exec_timestamp"); + + b.Property("HostUsername") + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("host_user"); + + b.Property("IsConfig") + .HasColumnType("BOOLEAN") + .HasColumnName("config"); + + b.Property("IsDebug") + .HasColumnType("BOOLEAN") + .HasColumnName("debug"); + + b.Property("IsExecFromGui") + .HasColumnType("BOOLEAN") + .HasColumnName("from_gui"); + + b.Property("Meta") + .IsRequired() + .HasColumnType("NVARCHAR2(2000)") + .HasColumnName("meta"); + + b.Property("PyRevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("pyrevit"); + + b.Property("ResultCode") + .HasColumnType("NUMBER(10)") + .HasColumnName("resultcode"); + + b.Property("RevitBuild") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("revitbuild"); + + b.Property("RevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("revit"); + + b.Property("ScriptPath") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("NVARCHAR2(1024)") + .HasColumnName("scriptpath"); + + b.Property("SessionId") + .HasColumnType("RAW(16)") + .HasColumnName("sessionid"); + + b.Property("Timestamp") + .HasColumnType("TIMESTAMP(7) WITH TIME ZONE") + .HasColumnName("timestamp"); + + b.Property("Trace") + .IsRequired() + .HasColumnType("NVARCHAR2(2000)") + .HasColumnName("trace"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("username"); + + b.HasKey("Id"); + + b.ToTable("script_record", (string)null); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Telemetry.Migrations.Oracle/Migrations/20260402141604_AddCancellableOracle.cs b/src/Telemetry.Migrations.Oracle/Migrations/20260402141604_AddCancellableOracle.cs new file mode 100644 index 0000000..67066bf --- /dev/null +++ b/src/Telemetry.Migrations.Oracle/Migrations/20260402141604_AddCancellableOracle.cs @@ -0,0 +1,28 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Telemetry.Migrations.Oracle.Migrations +{ + /// + public partial class AddCancellableOracle : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.RenameColumn( + name: "Cancellable", + table: "event_record", + newName: "cancellable"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.RenameColumn( + name: "cancellable", + table: "event_record", + newName: "Cancellable"); + } + } +} diff --git a/src/Telemetry.Migrations.Oracle/Migrations/ApplicationDbContextModelSnapshot.cs b/src/Telemetry.Migrations.Oracle/Migrations/ApplicationDbContextModelSnapshot.cs index 4da5e69..56dca43 100644 --- a/src/Telemetry.Migrations.Oracle/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/src/Telemetry.Migrations.Oracle/Migrations/ApplicationDbContextModelSnapshot.cs @@ -30,7 +30,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnName("id"); b.Property("Cancellable") - .HasColumnType("BOOLEAN"); + .HasColumnType("BOOLEAN") + .HasColumnName("cancellable"); b.Property("Cancelled") .HasColumnType("BOOLEAN") diff --git a/src/Telemetry.Migrations.Postgres/Migrations/20260402141612_AddCancellablePostgres.Designer.cs b/src/Telemetry.Migrations.Postgres/Migrations/20260402141612_AddCancellablePostgres.Designer.cs new file mode 100644 index 0000000..7fb51e5 --- /dev/null +++ b/src/Telemetry.Migrations.Postgres/Migrations/20260402141612_AddCancellablePostgres.Designer.cs @@ -0,0 +1,272 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using Telemetry.Api.Infrastructure.Persistence; + +#nullable disable + +namespace Telemetry.Migrations.Postgres.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20260402141612_AddCancellablePostgres")] + partial class AddCancellablePostgres + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "10.0.5") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Telemetry.Api.Domain.Models.EventRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("Cancellable") + .HasColumnType("boolean") + .HasColumnName("cancellable"); + + b.Property("Cancelled") + .HasColumnType("boolean") + .HasColumnName("cancelled"); + + b.Property("DocumentId") + .HasColumnType("integer") + .HasColumnName("docid"); + + b.Property("DocumentName") + .HasMaxLength(250) + .HasColumnType("character varying(250)") + .HasColumnName("docname"); + + b.Property("DocumentPath") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("docpath"); + + b.Property("DocumentTemplate") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("doctemplate"); + + b.Property("DocumentType") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("doctype"); + + b.Property("EventArgs") + .HasMaxLength(8000) + .HasColumnType("character varying(8000)") + .HasColumnName("args"); + + b.Property("EventType") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("type"); + + b.Property("HandlerId") + .HasColumnType("uuid") + .HasColumnName("handler_id"); + + b.Property("HostUsername") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("host_user"); + + b.Property("Meta") + .IsRequired() + .HasColumnType("text") + .HasColumnName("meta"); + + b.Property("ProjectName") + .HasMaxLength(250) + .HasColumnType("character varying(250)") + .HasColumnName("projectname"); + + b.Property("ProjectNum") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("projectnum"); + + b.Property("RevitBuild") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("revitbuild"); + + b.Property("RevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("revit"); + + b.Property("Status") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("status"); + + b.Property("Timestamp") + .HasColumnType("timestamp with time zone") + .HasColumnName("timestamp"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("username"); + + b.HasKey("Id"); + + b.ToTable("event_record", (string)null); + }); + + modelBuilder.Entity("Telemetry.Api.Domain.Models.ScriptRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("CloneName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("clone"); + + b.Property("CommandBundle") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)") + .HasColumnName("commandbundle"); + + b.Property("CommandExtension") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)") + .HasColumnName("commandextension"); + + b.Property("CommandName") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)") + .HasColumnName("commandname"); + + b.Property("CommandResults") + .HasMaxLength(8000) + .HasColumnType("character varying(8000)") + .HasColumnName("commandresults"); + + b.Property("CommandUniqueName") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("character varying(500)") + .HasColumnName("commanduniquename"); + + b.Property("DocumentName") + .HasMaxLength(250) + .HasColumnType("character varying(250)") + .HasColumnName("docname"); + + b.Property("DocumentPath") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("docpath"); + + b.Property("ExecId") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("exec_id"); + + b.Property("ExecTimestamp") + .HasColumnType("timestamp with time zone") + .HasColumnName("exec_timestamp"); + + b.Property("HostUsername") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("host_user"); + + b.Property("IsConfig") + .HasColumnType("boolean") + .HasColumnName("config"); + + b.Property("IsDebug") + .HasColumnType("boolean") + .HasColumnName("debug"); + + b.Property("IsExecFromGui") + .HasColumnType("boolean") + .HasColumnName("from_gui"); + + b.Property("Meta") + .IsRequired() + .HasColumnType("text") + .HasColumnName("meta"); + + b.Property("PyRevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("pyrevit"); + + b.Property("ResultCode") + .HasColumnType("integer") + .HasColumnName("resultcode"); + + b.Property("RevitBuild") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("revitbuild"); + + b.Property("RevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("revit"); + + b.Property("ScriptPath") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("scriptpath"); + + b.Property("SessionId") + .HasColumnType("uuid") + .HasColumnName("sessionid"); + + b.Property("Timestamp") + .HasColumnType("timestamp with time zone") + .HasColumnName("timestamp"); + + b.Property("Trace") + .IsRequired() + .HasColumnType("text") + .HasColumnName("trace"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("username"); + + b.HasKey("Id"); + + b.ToTable("script_record", (string)null); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Telemetry.Migrations.Postgres/Migrations/20260402141612_AddCancellablePostgres.cs b/src/Telemetry.Migrations.Postgres/Migrations/20260402141612_AddCancellablePostgres.cs new file mode 100644 index 0000000..5258089 --- /dev/null +++ b/src/Telemetry.Migrations.Postgres/Migrations/20260402141612_AddCancellablePostgres.cs @@ -0,0 +1,28 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Telemetry.Migrations.Postgres.Migrations +{ + /// + public partial class AddCancellablePostgres : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.RenameColumn( + name: "Cancellable", + table: "event_record", + newName: "cancellable"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.RenameColumn( + name: "cancellable", + table: "event_record", + newName: "Cancellable"); + } + } +} diff --git a/src/Telemetry.Migrations.Postgres/Migrations/ApplicationDbContextModelSnapshot.cs b/src/Telemetry.Migrations.Postgres/Migrations/ApplicationDbContextModelSnapshot.cs index 89d9395..35a3fd4 100644 --- a/src/Telemetry.Migrations.Postgres/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/src/Telemetry.Migrations.Postgres/Migrations/ApplicationDbContextModelSnapshot.cs @@ -30,7 +30,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnName("id"); b.Property("Cancellable") - .HasColumnType("boolean"); + .HasColumnType("boolean") + .HasColumnName("cancellable"); b.Property("Cancelled") .HasColumnType("boolean") diff --git a/src/Telemetry.Migrations.SqlServer/Migrations/20260402141635_AddCancellableSqlServer.Designer.cs b/src/Telemetry.Migrations.SqlServer/Migrations/20260402141635_AddCancellableSqlServer.Designer.cs new file mode 100644 index 0000000..9c2b98d --- /dev/null +++ b/src/Telemetry.Migrations.SqlServer/Migrations/20260402141635_AddCancellableSqlServer.Designer.cs @@ -0,0 +1,272 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Telemetry.Api.Infrastructure.Persistence; + +#nullable disable + +namespace Telemetry.Migrations.SqlServer.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20260402141635_AddCancellableSqlServer")] + partial class AddCancellableSqlServer + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "10.0.5") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Telemetry.Api.Domain.Models.EventRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnName("id"); + + b.Property("Cancellable") + .HasColumnType("bit") + .HasColumnName("cancellable"); + + b.Property("Cancelled") + .HasColumnType("bit") + .HasColumnName("cancelled"); + + b.Property("DocumentId") + .HasColumnType("int") + .HasColumnName("docid"); + + b.Property("DocumentName") + .HasMaxLength(250) + .HasColumnType("nvarchar(250)") + .HasColumnName("docname"); + + b.Property("DocumentPath") + .HasMaxLength(1024) + .HasColumnType("nvarchar(1024)") + .HasColumnName("docpath"); + + b.Property("DocumentTemplate") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("doctemplate"); + + b.Property("DocumentType") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("doctype"); + + b.Property("EventArgs") + .HasMaxLength(8000) + .HasColumnType("nvarchar(max)") + .HasColumnName("args"); + + b.Property("EventType") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("type"); + + b.Property("HandlerId") + .HasColumnType("uniqueidentifier") + .HasColumnName("handler_id"); + + b.Property("HostUsername") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("host_user"); + + b.Property("Meta") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("meta"); + + b.Property("ProjectName") + .HasMaxLength(250) + .HasColumnType("nvarchar(250)") + .HasColumnName("projectname"); + + b.Property("ProjectNum") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("projectnum"); + + b.Property("RevitBuild") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("revitbuild"); + + b.Property("RevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("revit"); + + b.Property("Status") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("status"); + + b.Property("Timestamp") + .HasColumnType("datetimeoffset") + .HasColumnName("timestamp"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("username"); + + b.HasKey("Id"); + + b.ToTable("event_record", (string)null); + }); + + modelBuilder.Entity("Telemetry.Api.Domain.Models.ScriptRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnName("id"); + + b.Property("CloneName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("clone"); + + b.Property("CommandBundle") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("nvarchar(250)") + .HasColumnName("commandbundle"); + + b.Property("CommandExtension") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("nvarchar(250)") + .HasColumnName("commandextension"); + + b.Property("CommandName") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("nvarchar(250)") + .HasColumnName("commandname"); + + b.Property("CommandResults") + .HasMaxLength(8000) + .HasColumnType("nvarchar(max)") + .HasColumnName("commandresults"); + + b.Property("CommandUniqueName") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("nvarchar(500)") + .HasColumnName("commanduniquename"); + + b.Property("DocumentName") + .HasMaxLength(250) + .HasColumnType("nvarchar(250)") + .HasColumnName("docname"); + + b.Property("DocumentPath") + .HasMaxLength(1024) + .HasColumnType("nvarchar(1024)") + .HasColumnName("docpath"); + + b.Property("ExecId") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("exec_id"); + + b.Property("ExecTimestamp") + .HasColumnType("datetimeoffset") + .HasColumnName("exec_timestamp"); + + b.Property("HostUsername") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("host_user"); + + b.Property("IsConfig") + .HasColumnType("bit") + .HasColumnName("config"); + + b.Property("IsDebug") + .HasColumnType("bit") + .HasColumnName("debug"); + + b.Property("IsExecFromGui") + .HasColumnType("bit") + .HasColumnName("from_gui"); + + b.Property("Meta") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("meta"); + + b.Property("PyRevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("pyrevit"); + + b.Property("ResultCode") + .HasColumnType("int") + .HasColumnName("resultcode"); + + b.Property("RevitBuild") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("revitbuild"); + + b.Property("RevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("revit"); + + b.Property("ScriptPath") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("nvarchar(1024)") + .HasColumnName("scriptpath"); + + b.Property("SessionId") + .HasColumnType("uniqueidentifier") + .HasColumnName("sessionid"); + + b.Property("Timestamp") + .HasColumnType("datetimeoffset") + .HasColumnName("timestamp"); + + b.Property("Trace") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("trace"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("username"); + + b.HasKey("Id"); + + b.ToTable("script_record", (string)null); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Telemetry.Migrations.SqlServer/Migrations/20260402141635_AddCancellableSqlServer.cs b/src/Telemetry.Migrations.SqlServer/Migrations/20260402141635_AddCancellableSqlServer.cs new file mode 100644 index 0000000..41f8ba0 --- /dev/null +++ b/src/Telemetry.Migrations.SqlServer/Migrations/20260402141635_AddCancellableSqlServer.cs @@ -0,0 +1,28 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Telemetry.Migrations.SqlServer.Migrations +{ + /// + public partial class AddCancellableSqlServer : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.RenameColumn( + name: "Cancellable", + table: "event_record", + newName: "cancellable"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.RenameColumn( + name: "cancellable", + table: "event_record", + newName: "Cancellable"); + } + } +} diff --git a/src/Telemetry.Migrations.SqlServer/Migrations/ApplicationDbContextModelSnapshot.cs b/src/Telemetry.Migrations.SqlServer/Migrations/ApplicationDbContextModelSnapshot.cs index e40673d..e43d7b4 100644 --- a/src/Telemetry.Migrations.SqlServer/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/src/Telemetry.Migrations.SqlServer/Migrations/ApplicationDbContextModelSnapshot.cs @@ -30,7 +30,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnName("id"); b.Property("Cancellable") - .HasColumnType("bit"); + .HasColumnType("bit") + .HasColumnName("cancellable"); b.Property("Cancelled") .HasColumnType("bit") diff --git a/src/Telemetry.Migrations.Sqlite/Migrations/20260402141622_AddCancellableSqlite.Designer.cs b/src/Telemetry.Migrations.Sqlite/Migrations/20260402141622_AddCancellableSqlite.Designer.cs new file mode 100644 index 0000000..5371bf9 --- /dev/null +++ b/src/Telemetry.Migrations.Sqlite/Migrations/20260402141622_AddCancellableSqlite.Designer.cs @@ -0,0 +1,267 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Telemetry.Api.Infrastructure.Persistence; + +#nullable disable + +namespace Telemetry.Migrations.Sqlite.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20260402141622_AddCancellableSqlite")] + partial class AddCancellableSqlite + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "10.0.5"); + + modelBuilder.Entity("Telemetry.Api.Domain.Models.EventRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT") + .HasColumnName("id"); + + b.Property("Cancellable") + .HasColumnType("INTEGER") + .HasColumnName("cancellable"); + + b.Property("Cancelled") + .HasColumnType("INTEGER") + .HasColumnName("cancelled"); + + b.Property("DocumentId") + .HasColumnType("INTEGER") + .HasColumnName("docid"); + + b.Property("DocumentName") + .HasMaxLength(250) + .HasColumnType("TEXT") + .HasColumnName("docname"); + + b.Property("DocumentPath") + .HasMaxLength(1024) + .HasColumnType("TEXT") + .HasColumnName("docpath"); + + b.Property("DocumentTemplate") + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("doctemplate"); + + b.Property("DocumentType") + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("doctype"); + + b.Property("EventArgs") + .HasMaxLength(8000) + .HasColumnType("TEXT") + .HasColumnName("args"); + + b.Property("EventType") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("type"); + + b.Property("HandlerId") + .HasColumnType("TEXT") + .HasColumnName("handler_id"); + + b.Property("HostUsername") + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("host_user"); + + b.Property("Meta") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("meta"); + + b.Property("ProjectName") + .HasMaxLength(250) + .HasColumnType("TEXT") + .HasColumnName("projectname"); + + b.Property("ProjectNum") + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("projectnum"); + + b.Property("RevitBuild") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("revitbuild"); + + b.Property("RevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("revit"); + + b.Property("Status") + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("status"); + + b.Property("Timestamp") + .HasColumnType("TEXT") + .HasColumnName("timestamp"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("username"); + + b.HasKey("Id"); + + b.ToTable("event_record", (string)null); + }); + + modelBuilder.Entity("Telemetry.Api.Domain.Models.ScriptRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT") + .HasColumnName("id"); + + b.Property("CloneName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("clone"); + + b.Property("CommandBundle") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("TEXT") + .HasColumnName("commandbundle"); + + b.Property("CommandExtension") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("TEXT") + .HasColumnName("commandextension"); + + b.Property("CommandName") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("TEXT") + .HasColumnName("commandname"); + + b.Property("CommandResults") + .HasMaxLength(8000) + .HasColumnType("TEXT") + .HasColumnName("commandresults"); + + b.Property("CommandUniqueName") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("TEXT") + .HasColumnName("commanduniquename"); + + b.Property("DocumentName") + .HasMaxLength(250) + .HasColumnType("TEXT") + .HasColumnName("docname"); + + b.Property("DocumentPath") + .HasMaxLength(1024) + .HasColumnType("TEXT") + .HasColumnName("docpath"); + + b.Property("ExecId") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("exec_id"); + + b.Property("ExecTimestamp") + .HasColumnType("TEXT") + .HasColumnName("exec_timestamp"); + + b.Property("HostUsername") + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("host_user"); + + b.Property("IsConfig") + .HasColumnType("INTEGER") + .HasColumnName("config"); + + b.Property("IsDebug") + .HasColumnType("INTEGER") + .HasColumnName("debug"); + + b.Property("IsExecFromGui") + .HasColumnType("INTEGER") + .HasColumnName("from_gui"); + + b.Property("Meta") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("meta"); + + b.Property("PyRevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("pyrevit"); + + b.Property("ResultCode") + .HasColumnType("INTEGER") + .HasColumnName("resultcode"); + + b.Property("RevitBuild") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("revitbuild"); + + b.Property("RevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("revit"); + + b.Property("ScriptPath") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("TEXT") + .HasColumnName("scriptpath"); + + b.Property("SessionId") + .HasColumnType("TEXT") + .HasColumnName("sessionid"); + + b.Property("Timestamp") + .HasColumnType("TEXT") + .HasColumnName("timestamp"); + + b.Property("Trace") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("trace"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("username"); + + b.HasKey("Id"); + + b.ToTable("script_record", (string)null); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Telemetry.Migrations.Sqlite/Migrations/20260402141622_AddCancellableSqlite.cs b/src/Telemetry.Migrations.Sqlite/Migrations/20260402141622_AddCancellableSqlite.cs new file mode 100644 index 0000000..1ef0e39 --- /dev/null +++ b/src/Telemetry.Migrations.Sqlite/Migrations/20260402141622_AddCancellableSqlite.cs @@ -0,0 +1,28 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Telemetry.Migrations.Sqlite.Migrations +{ + /// + public partial class AddCancellableSqlite : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.RenameColumn( + name: "Cancellable", + table: "event_record", + newName: "cancellable"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.RenameColumn( + name: "cancellable", + table: "event_record", + newName: "Cancellable"); + } + } +} diff --git a/src/Telemetry.Migrations.Sqlite/Migrations/ApplicationDbContextModelSnapshot.cs b/src/Telemetry.Migrations.Sqlite/Migrations/ApplicationDbContextModelSnapshot.cs index 0cedbb7..0fc6f6d 100644 --- a/src/Telemetry.Migrations.Sqlite/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/src/Telemetry.Migrations.Sqlite/Migrations/ApplicationDbContextModelSnapshot.cs @@ -25,7 +25,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnName("id"); b.Property("Cancellable") - .HasColumnType("INTEGER"); + .HasColumnType("INTEGER") + .HasColumnName("cancellable"); b.Property("Cancelled") .HasColumnType("INTEGER") From a9637b10e1482cc4c4f40e08effe12e4b931c103 Mon Sep 17 00:00:00 2001 From: dosymep Date: Thu, 2 Apr 2026 20:38:41 +0600 Subject: [PATCH 15/31] add shared project files to Docker image build context --- src/Telemetry.Api/Dockerfile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Telemetry.Api/Dockerfile b/src/Telemetry.Api/Dockerfile index 5542d6c..bb6eb9c 100644 --- a/src/Telemetry.Api/Dockerfile +++ b/src/Telemetry.Api/Dockerfile @@ -14,6 +14,10 @@ FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build ARG BUILD_CONFIGURATION=Release WORKDIR /src +COPY ["Directory.Build.props", "Directory.Build.props"] +COPY ["Directory.Build.targets", "Directory.Build.targets"] +COPY ["Directory.Packages.props", "Directory.Packages.props"] + COPY ["src/Telemetry.Api/Telemetry.Api.csproj", "Telemetry.Api/"] COPY ["src/Telemetry.Migrations.Oracle/Telemetry.Migrations.Oracle.csproj", "Telemetry.Migrations.Oracle/"] COPY ["src/Telemetry.Migrations.Postgres/Telemetry.Migrations.Postgres.csproj", "Telemetry.Migrations.Postgres/"] From a704e3017afa0c1a66509e1639075fcf4f14afe4 Mon Sep 17 00:00:00 2001 From: dosymep Date: Mon, 6 Apr 2026 15:58:59 +0600 Subject: [PATCH 16/31] fix parsing dto --- .../Application/DTOs/EngineInfoDto.cs | 2 + .../Application/DTOs/EventRecordDto.cs | 2 + .../Application/DTOs/ScriptRecordDto.cs | 2 + src/Telemetry.Api/Domain/Models/EngineInfo.cs | 12 +- .../Domain/Models/EventRecord.cs | 21 -- src/Telemetry.Api/Domain/Models/MetaRecord.cs | 3 +- .../Domain/Models/ScriptRecord.cs | 36 +-- src/Telemetry.Api/Domain/Models/TraceInfo.cs | 5 +- .../Persistence/ApplicationDbContext.cs | 235 ++++++++++++++---- .../DynamicDataJsonConverter.cs | 3 +- src/Telemetry.Api/Telemetry.Api.http | 25 +- 11 files changed, 233 insertions(+), 113 deletions(-) diff --git a/src/Telemetry.Api/Application/DTOs/EngineInfoDto.cs b/src/Telemetry.Api/Application/DTOs/EngineInfoDto.cs index 4ef8e30..426abe1 100644 --- a/src/Telemetry.Api/Application/DTOs/EngineInfoDto.cs +++ b/src/Telemetry.Api/Application/DTOs/EngineInfoDto.cs @@ -1,5 +1,6 @@ using System.ComponentModel.DataAnnotations; using System.Text.Json.Serialization; +using Telemetry.Api.JsonConverters; namespace Telemetry.Api.Application.DTOs { @@ -35,6 +36,7 @@ public class EngineInfoDto /// [MaxLength(8000)] [JsonPropertyName("configs")] + [JsonConverter(typeof(DynamicDataJsonConverter))] public string? Configs { get; init; } } } \ No newline at end of file diff --git a/src/Telemetry.Api/Application/DTOs/EventRecordDto.cs b/src/Telemetry.Api/Application/DTOs/EventRecordDto.cs index 02fa383..188b658 100644 --- a/src/Telemetry.Api/Application/DTOs/EventRecordDto.cs +++ b/src/Telemetry.Api/Application/DTOs/EventRecordDto.cs @@ -1,5 +1,6 @@ using System.ComponentModel.DataAnnotations; using System.Text.Json.Serialization; +using Telemetry.Api.JsonConverters; namespace Telemetry.Api.Application.DTOs { @@ -159,6 +160,7 @@ public class EventRecordDto /// [MaxLength(8000)] [JsonPropertyName("args")] + [JsonConverter(typeof(DynamicDataJsonConverter))] public string? EventArgs { get; init; } } } \ No newline at end of file diff --git a/src/Telemetry.Api/Application/DTOs/ScriptRecordDto.cs b/src/Telemetry.Api/Application/DTOs/ScriptRecordDto.cs index 0949f88..9a65581 100644 --- a/src/Telemetry.Api/Application/DTOs/ScriptRecordDto.cs +++ b/src/Telemetry.Api/Application/DTOs/ScriptRecordDto.cs @@ -1,5 +1,6 @@ using System.ComponentModel.DataAnnotations; using System.Text.Json.Serialization; +using Telemetry.Api.JsonConverters; namespace Telemetry.Api.Application.DTOs { @@ -181,6 +182,7 @@ public class ScriptRecordDto /// [MaxLength(8000)] [JsonPropertyName("commandresults")] + [JsonConverter(typeof(DynamicDataJsonConverter))] public string? CommandResults { get; init; } } } \ No newline at end of file diff --git a/src/Telemetry.Api/Domain/Models/EngineInfo.cs b/src/Telemetry.Api/Domain/Models/EngineInfo.cs index e1512af..5adef1e 100644 --- a/src/Telemetry.Api/Domain/Models/EngineInfo.cs +++ b/src/Telemetry.Api/Domain/Models/EngineInfo.cs @@ -1,5 +1,7 @@ using MongoDB.Bson.Serialization.Attributes; using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; +using Telemetry.Api.JsonConverters; namespace Telemetry.Api.Domain.Models { @@ -13,7 +15,7 @@ public class EngineInfo ///
Engine types. /// [MaxLength(100)] - [BsonElement("type")] + [JsonPropertyName("type")] public required string Type { get; init; } /// @@ -21,20 +23,20 @@ public class EngineInfo ///
Engines list. ///
[MaxLength(100)] - [BsonElement("version")] + [JsonPropertyName("version")] public required string Version { get; init; } /// /// System paths using by script. /// - [BsonElement("syspath")] + [JsonPropertyName("syspath")] public string[]? SysPaths { get; init; } /// /// Dynamic script configs data. /// - [MaxLength(8000)] - [BsonElement("configs")] + [MaxLength(8000)] + [JsonPropertyName("configs")] public string? Configs { get; init; } } } \ No newline at end of file diff --git a/src/Telemetry.Api/Domain/Models/EventRecord.cs b/src/Telemetry.Api/Domain/Models/EventRecord.cs index 227c685..9efbabe 100644 --- a/src/Telemetry.Api/Domain/Models/EventRecord.cs +++ b/src/Telemetry.Api/Domain/Models/EventRecord.cs @@ -8,7 +8,6 @@ namespace Telemetry.Api.Domain.Models /// /// Event record information. /// - [Table("events")] public class EventRecord { /// @@ -19,20 +18,17 @@ public class EventRecord /// /// Unique event id. /// - [BsonElement("handler_id")] public Guid HandlerId { get; init; } /// /// Information about telemetry record. /// - [BsonElement("meta")] public required MetaRecord Meta { get; init; } /// /// Event type name. /// [MaxLength(100)] - [BsonElement("type")] public required string EventType { get; init; } /// @@ -40,14 +36,11 @@ public class EventRecord /// status. /// [MaxLength(100)] - [BsonElement("status")] public string? Status { get; init; } /// /// When event started. /// - [BsonElement("timestamp")] - [BsonRepresentation(BsonType.DateTime)] public DateTimeOffset Timestamp { get; init; } /// @@ -55,7 +48,6 @@ public class EventRecord /// who use Autodesk Revit (sets in options). /// [MaxLength(100)] - [BsonElement("username")] public required string Username { get; init; } /// @@ -63,7 +55,6 @@ public class EventRecord /// who logged in Windows. /// [MaxLength(100)] - [BsonElement("host_user")] public string? HostUsername { get; init; } /// @@ -72,7 +63,6 @@ public class EventRecord /// of the Autodesk Revit application. /// [MaxLength(100)] - [BsonElement("revitbuild")] public required string RevitBuild { get; init; } /// @@ -81,7 +71,6 @@ public class EventRecord /// of the Revit application. /// [MaxLength(100)] - [BsonElement("revit")] public required string RevitVersion { get; init; } /// @@ -89,7 +78,6 @@ public class EventRecord ///
RevitAPIEventArgs /// IsCancelled method. ///
- [BsonElement("cancelled")] public bool? Cancelled { get; init; } /// @@ -97,7 +85,6 @@ public class EventRecord ///
RevitAPIEventArgs /// Cancellable property. ///
- [BsonElement("cancellable")] public bool? Cancellable { get; init; } /// @@ -107,7 +94,6 @@ public class EventRecord ///
DocumentClosedEventArgs /// DocumentId property. ///
- [BsonElement("docid")] public int DocumentId { get; init; } /// @@ -120,7 +106,6 @@ public class EventRecord /// DocumentType property. /// [MaxLength(100)] - [BsonElement("doctype")] public string? DocumentType { get; init; } /// @@ -129,14 +114,12 @@ public class EventRecord /// Template property. /// [MaxLength(100)] - [BsonElement("doctemplate")] public string? DocumentTemplate { get; init; } /// /// Document Title property. /// [MaxLength(250)] - [BsonElement("docname")] public string? DocumentName { get; init; } /// @@ -144,7 +127,6 @@ public class EventRecord /// property. /// [MaxLength(1024)] - [BsonElement("docpath")] public string? DocumentPath { get; init; } /// @@ -152,7 +134,6 @@ public class EventRecord /// (BuiltInParameter.PROJECT_NAME). /// [MaxLength(250)] - [BsonElement("projectname")] public string? ProjectName { get; init; } /// @@ -160,14 +141,12 @@ public class EventRecord /// (BuiltInParameter.PROJECT_NUMBER). /// [MaxLength(100)] - [BsonElement("projectnum")] public string? ProjectNum { get; init; } /// /// Dynamic event args data. /// [MaxLength(8000)] - [BsonElement("args")] public string? EventArgs { get; init; } } } \ No newline at end of file diff --git a/src/Telemetry.Api/Domain/Models/MetaRecord.cs b/src/Telemetry.Api/Domain/Models/MetaRecord.cs index 9428dc2..687de6b 100644 --- a/src/Telemetry.Api/Domain/Models/MetaRecord.cs +++ b/src/Telemetry.Api/Domain/Models/MetaRecord.cs @@ -1,4 +1,5 @@ using MongoDB.Bson.Serialization.Attributes; +using System.Text.Json.Serialization; namespace Telemetry.Api.Domain.Models { @@ -10,7 +11,7 @@ public class MetaRecord /// /// Schema version. /// - [BsonElement("schema")] + [JsonPropertyName("version")] public required Version SchemaVersion { get; init; } } } \ No newline at end of file diff --git a/src/Telemetry.Api/Domain/Models/ScriptRecord.cs b/src/Telemetry.Api/Domain/Models/ScriptRecord.cs index c49ca07..ef29b27 100644 --- a/src/Telemetry.Api/Domain/Models/ScriptRecord.cs +++ b/src/Telemetry.Api/Domain/Models/ScriptRecord.cs @@ -2,13 +2,14 @@ using MongoDB.Bson.Serialization.Attributes; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; +using System.Text.Json.Serialization; +using Telemetry.Api.JsonConverters; namespace Telemetry.Api.Domain.Models { /// /// Script record information. /// - [Table("scripts")] public class ScriptRecord { /// @@ -19,20 +20,16 @@ public class ScriptRecord /// /// Unique session id (created when revit is opened). /// - [BsonElement("sessionid")] public Guid SessionId { get; init; } /// /// Information about telemetry record. /// - [BsonElement("meta")] public required MetaRecord Meta { get; init; } /// /// When script started. /// - [BsonElement("timestamp")] - [BsonRepresentation(BsonType.DateTime)] public DateTimeOffset Timestamp { get; init; } /// @@ -40,7 +37,6 @@ public class ScriptRecord /// who use Autodesk Revit (sets in options). /// [MaxLength(100)] - [BsonElement("username")] public required string Username { get; init; } /// @@ -48,7 +44,6 @@ public class ScriptRecord /// who logged in Windows. /// [MaxLength(100)] - [BsonElement("host_user")] public string? HostUsername { get; init; } /// @@ -56,8 +51,7 @@ public class ScriptRecord /// build number /// of the Autodesk Revit application. /// - [MaxLength(100)] - [BsonElement("revitbuild")] + [MaxLength(100)] public required string RevitBuild { get; init; } /// @@ -65,15 +59,13 @@ public class ScriptRecord /// primary version /// of the Revit application. /// - [MaxLength(100)] - [BsonElement("revit")] + [MaxLength(100)] public required string RevitVersion { get; init; } /// /// pyrevit build version. /// - [MaxLength(100)] - [BsonElement("pyrevit")] + [MaxLength(100)] public required string PyRevitVersion { get; init; } /// @@ -81,7 +73,6 @@ public class ScriptRecord /// clone name. /// [MaxLength(100)] - [BsonElement("clone")] public required string CloneName { get; init; } /// @@ -92,7 +83,6 @@ public class ScriptRecord /// mode /// . /// - [BsonElement("debug")] public bool IsDebug { get; init; } /// @@ -105,56 +95,47 @@ public class ScriptRecord /// /// If script was run from GUI (Click Revit Ribbon) , otherwise . /// - [BsonElement("from_gui")] public bool IsExecFromGui { get; init; } /// /// Unique execution id. /// [MaxLength(100)] - [BsonElement("exec_id")] public required string ExecId { get; init; } /// /// When script executed. /// - [BsonElement("exec_timestamp")] - [BsonRepresentation(BsonType.DateTime)] public DateTimeOffset ExecTimestamp { get; init; } /// /// Command bundle name. /// [MaxLength(250)] - [BsonElement("commandbundle")] public required string CommandBundle { get; init; } /// /// Command extension name. /// [MaxLength(250)] - [BsonElement("commandextension")] public required string CommandExtension { get; init; } /// /// Command name. /// [MaxLength(250)] - [BsonElement("commandname")] public required string CommandName { get; init; } /// /// Command unique name. /// [MaxLength(500)] - [BsonElement("commanduniquename")] public required string CommandUniqueName { get; init; } /// /// Document Title property. /// [MaxLength(250)] - [BsonElement("docname")] public string? DocumentName { get; init; } /// @@ -162,7 +143,6 @@ public class ScriptRecord /// property. /// [MaxLength(1024)] - [BsonElement("docpath")] public string? DocumentPath { get; init; } /// @@ -170,27 +150,23 @@ public class ScriptRecord ///
ResultCode /// enumeration. ///
- [BsonElement("resultcode")] public int ResultCode { get; init; } /// /// Executed script path. /// [MaxLength(1024)] - [BsonElement("scriptpath")] public required string ScriptPath { get; init; } /// /// Information about execution. /// - [BsonElement("trace")] public required TraceInfo Trace { get; init; } /// /// Additional command results. /// - [MaxLength(8000)] - [BsonElement("commandresults")] + [MaxLength(8000)] public string? CommandResults { get; init; } } } \ No newline at end of file diff --git a/src/Telemetry.Api/Domain/Models/TraceInfo.cs b/src/Telemetry.Api/Domain/Models/TraceInfo.cs index 3a852bd..9541426 100644 --- a/src/Telemetry.Api/Domain/Models/TraceInfo.cs +++ b/src/Telemetry.Api/Domain/Models/TraceInfo.cs @@ -1,5 +1,6 @@ using MongoDB.Bson.Serialization.Attributes; using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; namespace Telemetry.Api.Domain.Models { @@ -13,13 +14,13 @@ public class TraceInfo /// message. ///
[MaxLength(8000)] - [BsonElement("message")] + [JsonPropertyName("message")] public required string Message { get; init; } /// /// Script engine information. /// - [BsonElement("engine")] + [JsonPropertyName("engine")] public required EngineInfo Engine { get; init; } } } \ No newline at end of file diff --git a/src/Telemetry.Api/Infrastructure/Persistence/ApplicationDbContext.cs b/src/Telemetry.Api/Infrastructure/Persistence/ApplicationDbContext.cs index de9398d..a7f2f08 100644 --- a/src/Telemetry.Api/Infrastructure/Persistence/ApplicationDbContext.cs +++ b/src/Telemetry.Api/Infrastructure/Persistence/ApplicationDbContext.cs @@ -1,5 +1,7 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.ChangeTracking; +using MongoDB.Bson; +using MongoDB.EntityFrameworkCore.Extensions; using System.Data; using System.Data.Common; using System.Text.Json; @@ -135,74 +137,207 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity(entity => { - entity.ToTable("script_record"); + entity.ToTable("scripts"); + entity.ToCollection("scripts"); entity.HasKey(e => e.Id); - entity.Property(e => e.Id).HasColumnName("id"); - entity.Property(e => e.SessionId).HasColumnName("sessionid"); - entity.Property(e => e.Timestamp).HasColumnName("timestamp"); - entity.Property(e => e.Username).HasColumnName("username"); - entity.Property(e => e.HostUsername).HasColumnName("host_user"); - entity.Property(e => e.RevitBuild).HasColumnName("revitbuild"); - entity.Property(e => e.RevitVersion).HasColumnName("revit"); - entity.Property(e => e.PyRevitVersion).HasColumnName("pyrevit"); - entity.Property(e => e.CloneName).HasColumnName("clone"); - entity.Property(e => e.IsDebug).HasColumnName("debug"); - entity.Property(e => e.IsConfig).HasColumnName("config"); - entity.Property(e => e.IsExecFromGui).HasColumnName("from_gui"); - entity.Property(e => e.ExecId).HasColumnName("exec_id"); - entity.Property(e => e.ExecTimestamp).HasColumnName("exec_timestamp"); - entity.Property(e => e.CommandBundle).HasColumnName("commandbundle"); - entity.Property(e => e.CommandExtension).HasColumnName("commandextension"); - entity.Property(e => e.CommandName).HasColumnName("commandname"); - entity.Property(e => e.CommandUniqueName).HasColumnName("commanduniquename"); - entity.Property(e => e.DocumentName).HasColumnName("docname"); - entity.Property(e => e.DocumentPath).HasColumnName("docpath"); - entity.Property(e => e.ResultCode).HasColumnName("resultcode"); - entity.Property(e => e.ScriptPath).HasColumnName("scriptpath"); - entity.Property(e => e.CommandResults).HasColumnName("commandresults"); + + entity.Property(e => e.Id) + .HasColumnName("_id") + .HasElementName("_id"); + + entity.Property(e => e.SessionId) + .HasColumnName("sessionid") + .HasElementName("sessionid"); + + entity.Property(e => e.Timestamp) + .HasColumnName("timestamp") + .HasElementName("timestamp") + .HasBsonRepresentation(BsonType.DateTime); + + entity.Property(e => e.Username) + .HasColumnName("username") + .HasElementName("username"); + + entity.Property(e => e.HostUsername) + .HasColumnName("host_user") + .HasElementName("host_user"); + + entity.Property(e => e.RevitBuild) + .HasColumnName("revitbuild") + .HasElementName("revitbuild"); + + entity.Property(e => e.RevitVersion) + .HasColumnName("revit") + .HasElementName("revit"); + + entity.Property(e => e.PyRevitVersion) + .HasColumnName("pyrevit") + .HasElementName("pyrevit"); + + entity.Property(e => e.CloneName) + .HasColumnName("clone") + .HasElementName("clone"); + + entity.Property(e => e.IsDebug) + .HasColumnName("debug") + .HasElementName("debug"); + + entity.Property(e => e.IsConfig) + .HasColumnName("config") + .HasElementName("config"); + + entity.Property(e => e.IsExecFromGui) + .HasColumnName("from_gui") + .HasElementName("from_gui"); + + entity.Property(e => e.ExecId) + .HasColumnName("exec_id") + .HasElementName("exec_id"); + + entity.Property(e => e.ExecTimestamp) + .HasColumnName("exec_timestamp") + .HasElementName("exec_timestamp") + .HasBsonRepresentation(BsonType.DateTime); + + entity.Property(e => e.CommandBundle) + .HasColumnName("commandbundle") + .HasElementName("commandbundle"); + + entity.Property(e => e.CommandExtension) + .HasColumnName("commandextension") + .HasElementName("commandextension"); + + entity.Property(e => e.CommandName) + .HasColumnName("commandname") + .HasElementName("commandname"); + + entity.Property(e => e.CommandUniqueName) + .HasColumnName("commanduniquename") + .HasElementName("commanduniquename"); + + entity.Property(e => e.DocumentName).HasColumnName("docname") + .HasElementName("docname"); + + entity.Property(e => e.DocumentPath) + .HasColumnName("docpath") + .HasElementName("docpath"); + + entity.Property(e => e.ResultCode) + .HasColumnName("resultcode") + .HasElementName("resultcode"); + + entity.Property(e => e.ScriptPath) + .HasColumnName("scriptpath") + .HasElementName("scriptpath"); + + entity.Property(e => e.CommandResults) + .HasColumnName("commandresults") + .HasElementName("commandresults"); entity.Property(e => e.Meta) .HasColumnName("meta") + .HasElementName("meta") .HasConversion( - v => JsonSerializer.Serialize(v, (JsonSerializerOptions?)null), - v => JsonSerializer.Deserialize(v, (JsonSerializerOptions?)null)!); + v => JsonSerializer.Serialize(v, JsonSerializerOptions.Web), + v => JsonSerializer.Deserialize(v, JsonSerializerOptions.Web)!); entity.Property(e => e.Trace) .HasColumnName("trace") + .HasElementName("trace") .HasConversion( - v => JsonSerializer.Serialize(v, (JsonSerializerOptions?)null), - v => JsonSerializer.Deserialize(v, (JsonSerializerOptions?)null)!); + v => JsonSerializer.Serialize(v, JsonSerializerOptions.Web), + v => JsonSerializer.Deserialize(v, JsonSerializerOptions.Web)!); }); modelBuilder.Entity(entity => { - entity.ToTable("event_record"); + entity.ToTable("events"); + entity.ToCollection("events"); entity.HasKey(e => e.Id); - entity.Property(e => e.Id).HasColumnName("id"); - entity.Property(e => e.HandlerId).HasColumnName("handler_id"); - entity.Property(e => e.EventType).HasColumnName("type"); - entity.Property(e => e.Status).HasColumnName("status"); - entity.Property(e => e.Timestamp).HasColumnName("timestamp"); - entity.Property(e => e.Username).HasColumnName("username"); - entity.Property(e => e.HostUsername).HasColumnName("host_user"); - entity.Property(e => e.RevitBuild).HasColumnName("revitbuild"); - entity.Property(e => e.RevitVersion).HasColumnName("revit"); - entity.Property(e => e.Cancelled).HasColumnName("cancelled"); - entity.Property(e => e.Cancellable).HasColumnName("cancellable"); - entity.Property(e => e.DocumentId).HasColumnName("docid"); - entity.Property(e => e.DocumentType).HasColumnName("doctype"); - entity.Property(e => e.DocumentTemplate).HasColumnName("doctemplate"); - entity.Property(e => e.DocumentName).HasColumnName("docname"); - entity.Property(e => e.DocumentPath).HasColumnName("docpath"); - entity.Property(e => e.ProjectName).HasColumnName("projectname"); - entity.Property(e => e.ProjectNum).HasColumnName("projectnum"); - entity.Property(e => e.EventArgs).HasColumnName("args"); + + entity.Property(e => e.Id) + .HasColumnName("_id") + .HasElementName("_id"); + + entity.Property(e => e.HandlerId) + .HasColumnName("handler_id") + .HasElementName("handler_id"); + + entity.Property(e => e.EventType) + .HasColumnName("type") + .HasElementName("type"); + + entity.Property(e => e.Status) + .HasColumnName("status") + .HasElementName("status"); + + entity.Property(e => e.Timestamp) + .HasColumnName("timestamp") + .HasElementName("timestamp") + .HasBsonRepresentation(BsonType.DateTime); + + entity.Property(e => e.Username) + .HasColumnName("username") + .HasElementName("username"); + + entity.Property(e => e.HostUsername) + .HasColumnName("host_user") + .HasElementName("host_user"); + + entity.Property(e => e.RevitBuild) + .HasColumnName("revitbuild") + .HasElementName("revitbuild"); + + entity.Property(e => e.RevitVersion) + .HasColumnName("revit") + .HasElementName("revit"); + + entity.Property(e => e.Cancelled) + .HasColumnName("cancelled") + .HasElementName("cancelled"); + + entity.Property(e => e.Cancellable) + .HasColumnName("cancellable") + .HasElementName("cancellable"); + + entity.Property(e => e.DocumentId) + .HasColumnName("docid") + .HasElementName("docid"); + + entity.Property(e => e.DocumentType) + .HasColumnName("doctype") + .HasElementName("doctype"); + + entity.Property(e => e.DocumentTemplate) + .HasColumnName("doctemplate") + .HasElementName("doctemplate"); + + entity.Property(e => e.DocumentName) + .HasColumnName("docname") + .HasElementName("docname"); + + entity.Property(e => e.DocumentPath) + .HasColumnName("docpath") + .HasElementName("docpath"); + + entity.Property(e => e.ProjectName) + .HasColumnName("projectname") + .HasElementName("projectname"); + + entity.Property(e => e.ProjectNum) + .HasColumnName("projectnum") + .HasElementName("projectnum"); + + entity.Property(e => e.EventArgs) + .HasColumnName("args") + .HasElementName("args"); entity.Property(e => e.Meta) .HasColumnName("meta") + .HasElementName("meta") .HasConversion( - v => JsonSerializer.Serialize(v, (JsonSerializerOptions?)null), - v => JsonSerializer.Deserialize(v, (JsonSerializerOptions?)null)!); + v => JsonSerializer.Serialize(v, JsonSerializerOptions.Web), + v => JsonSerializer.Deserialize(v, JsonSerializerOptions.Web)!); }); base.OnModelCreating(modelBuilder); diff --git a/src/Telemetry.Api/JsonConverters/DynamicDataJsonConverter.cs b/src/Telemetry.Api/JsonConverters/DynamicDataJsonConverter.cs index 50515a4..8522540 100644 --- a/src/Telemetry.Api/JsonConverters/DynamicDataJsonConverter.cs +++ b/src/Telemetry.Api/JsonConverters/DynamicDataJsonConverter.cs @@ -12,7 +12,8 @@ internal class DynamicDataJsonConverter : JsonConverter return null; } - return JsonDocument.ParseValue(ref reader).RootElement.GetRawText(); + using JsonDocument parsed = JsonDocument.ParseValue(ref reader); + return parsed.RootElement.GetRawText(); } public override void Write(Utf8JsonWriter writer, string? value, JsonSerializerOptions options) diff --git a/src/Telemetry.Api/Telemetry.Api.http b/src/Telemetry.Api/Telemetry.Api.http index 14971eb..08cb095 100644 --- a/src/Telemetry.Api/Telemetry.Api.http +++ b/src/Telemetry.Api/Telemetry.Api.http @@ -39,9 +39,22 @@ Content-Type: application/json "path1", "path2" ], - "configs": "test configs" + "configs": { + "config": 1, + "version": 12, + "some_object": { + "hey": "hey" + }, + "some_array": [ + 1, + 2, + 3, + 4 + ] + } } - } + }, + "commandresults": {} } ### Post Event Record @@ -67,7 +80,13 @@ Content-Type: application/json "docname": "doc name", "docpath": "C:\\doc.rvt", "projectname": "doc.rvt", - "projectnum": "projectnum" + "projectnum": "projectnum", + "args": { + "operation": "transaction", + "added": 1, + "deleted": 2, + "modified": 4 + } } ### Get Prometheus Metrics From a114a0dca9193ba2c331cd235fb14c36cfbcf1c3 Mon Sep 17 00:00:00 2001 From: dosymep Date: Mon, 6 Apr 2026 16:07:14 +0600 Subject: [PATCH 17/31] update tests --- .../MongoDbIntegrationTests.cs | 29 +++++++++++ .../MsSqlIntegrationTests.cs | 29 +++++++++++ .../OracleIntegrationTests.cs | 29 +++++++++++ .../PostgresIntegrationTests.cs | 29 +++++++++++ .../SqliteIntegrationTests.cs | 29 +++++++++++ .../Telemetry.Api.IntegrationTests.csproj | 4 -- .../assets/event.json | 27 +++++++++++ .../assets/script.json | 48 +++++++++++++++++++ 8 files changed, 220 insertions(+), 4 deletions(-) create mode 100644 tests/Telemetry.Api.IntegrationTests/assets/event.json create mode 100644 tests/Telemetry.Api.IntegrationTests/assets/script.json diff --git a/tests/Telemetry.Api.IntegrationTests/MongoDbIntegrationTests.cs b/tests/Telemetry.Api.IntegrationTests/MongoDbIntegrationTests.cs index eafd21a..a84deaf 100644 --- a/tests/Telemetry.Api.IntegrationTests/MongoDbIntegrationTests.cs +++ b/tests/Telemetry.Api.IntegrationTests/MongoDbIntegrationTests.cs @@ -1,3 +1,4 @@ +using System.Text; using Telemetry.Api.Application.DTOs; using Testcontainers.MongoDb; @@ -63,5 +64,33 @@ public async Task PostEvent_ReturnsOk() // Assert response.EnsureSuccessStatusCode(); } + + [Test] + public async Task PostRawScript_ReturnsOk() + { + // Arrange + var content = await File.ReadAllTextAsync("assets/script.json"); + var stringContent = new StringContent(content, Encoding.UTF8, "application/json"); + + // Act + HttpResponseMessage response = await Client.PostAsync("/api/v2/scripts", stringContent); + + // Assert + response.EnsureSuccessStatusCode(); + } + + [Test] + public async Task PostRawEvent_ReturnsOk() + { + // Arrange + var content = await File.ReadAllTextAsync("assets/event.json"); + var stringContent = new StringContent(content, Encoding.UTF8, "application/json"); + + // Act + HttpResponseMessage response = await Client.PostAsync("/api/v2/events", stringContent); + + // Assert + response.EnsureSuccessStatusCode(); + } } } \ No newline at end of file diff --git a/tests/Telemetry.Api.IntegrationTests/MsSqlIntegrationTests.cs b/tests/Telemetry.Api.IntegrationTests/MsSqlIntegrationTests.cs index 55474c8..c75bc19 100644 --- a/tests/Telemetry.Api.IntegrationTests/MsSqlIntegrationTests.cs +++ b/tests/Telemetry.Api.IntegrationTests/MsSqlIntegrationTests.cs @@ -1,3 +1,4 @@ +using System.Text; using Telemetry.Api.Application.DTOs; using Testcontainers.MsSql; @@ -62,5 +63,33 @@ public async Task PostEvent_ReturnsOk() // Assert response.EnsureSuccessStatusCode(); } + + [Test] + public async Task PostRawScript_ReturnsOk() + { + // Arrange + var content = await File.ReadAllTextAsync("assets/script.json"); + var stringContent = new StringContent(content, Encoding.UTF8, "application/json"); + + // Act + HttpResponseMessage response = await Client.PostAsync("/api/v2/scripts", stringContent); + + // Assert + response.EnsureSuccessStatusCode(); + } + + [Test] + public async Task PostRawEvent_ReturnsOk() + { + // Arrange + var content = await File.ReadAllTextAsync("assets/event.json"); + var stringContent = new StringContent(content, Encoding.UTF8, "application/json"); + + // Act + HttpResponseMessage response = await Client.PostAsync("/api/v2/events", stringContent); + + // Assert + response.EnsureSuccessStatusCode(); + } } } \ No newline at end of file diff --git a/tests/Telemetry.Api.IntegrationTests/OracleIntegrationTests.cs b/tests/Telemetry.Api.IntegrationTests/OracleIntegrationTests.cs index de0dd76..ee68d50 100644 --- a/tests/Telemetry.Api.IntegrationTests/OracleIntegrationTests.cs +++ b/tests/Telemetry.Api.IntegrationTests/OracleIntegrationTests.cs @@ -1,3 +1,4 @@ +using System.Text; using Telemetry.Api.Application.DTOs; using Testcontainers.Oracle; @@ -62,5 +63,33 @@ public async Task PostEvent_ReturnsOk() // Assert response.EnsureSuccessStatusCode(); } + + [Test] + public async Task PostRawScript_ReturnsOk() + { + // Arrange + var content = await File.ReadAllTextAsync("assets/script.json"); + var stringContent = new StringContent(content, Encoding.UTF8, "application/json"); + + // Act + HttpResponseMessage response = await Client.PostAsync("/api/v2/scripts", stringContent); + + // Assert + response.EnsureSuccessStatusCode(); + } + + [Test] + public async Task PostRawEvent_ReturnsOk() + { + // Arrange + var content = await File.ReadAllTextAsync("assets/event.json"); + var stringContent = new StringContent(content, Encoding.UTF8, "application/json"); + + // Act + HttpResponseMessage response = await Client.PostAsync("/api/v2/events", stringContent); + + // Assert + response.EnsureSuccessStatusCode(); + } } } \ No newline at end of file diff --git a/tests/Telemetry.Api.IntegrationTests/PostgresIntegrationTests.cs b/tests/Telemetry.Api.IntegrationTests/PostgresIntegrationTests.cs index 0e7b7bd..8d0d7be 100644 --- a/tests/Telemetry.Api.IntegrationTests/PostgresIntegrationTests.cs +++ b/tests/Telemetry.Api.IntegrationTests/PostgresIntegrationTests.cs @@ -1,3 +1,4 @@ +using System.Text; using Telemetry.Api.Application.DTOs; using Testcontainers.PostgreSql; @@ -62,5 +63,33 @@ public async Task PostEvent_ReturnsOk() // Assert response.EnsureSuccessStatusCode(); } + + [Test] + public async Task PostRawScript_ReturnsOk() + { + // Arrange + var content = await File.ReadAllTextAsync("assets/script.json"); + var stringContent = new StringContent(content, Encoding.UTF8, "application/json"); + + // Act + HttpResponseMessage response = await Client.PostAsync("/api/v2/scripts", stringContent); + + // Assert + response.EnsureSuccessStatusCode(); + } + + [Test] + public async Task PostRawEvent_ReturnsOk() + { + // Arrange + var content = await File.ReadAllTextAsync("assets/event.json"); + var stringContent = new StringContent(content, Encoding.UTF8, "application/json"); + + // Act + HttpResponseMessage response = await Client.PostAsync("/api/v2/events", stringContent); + + // Assert + response.EnsureSuccessStatusCode(); + } } } \ No newline at end of file diff --git a/tests/Telemetry.Api.IntegrationTests/SqliteIntegrationTests.cs b/tests/Telemetry.Api.IntegrationTests/SqliteIntegrationTests.cs index 12e8bf7..a51c337 100644 --- a/tests/Telemetry.Api.IntegrationTests/SqliteIntegrationTests.cs +++ b/tests/Telemetry.Api.IntegrationTests/SqliteIntegrationTests.cs @@ -1,3 +1,4 @@ +using System.Text; using Telemetry.Api.Application.DTOs; namespace Telemetry.Api.IntegrationTests @@ -61,5 +62,33 @@ public async Task PostEvent_ReturnsOk() // Assert response.EnsureSuccessStatusCode(); } + + [Test] + public async Task PostRawScript_ReturnsOk() + { + // Arrange + var content = await File.ReadAllTextAsync("assets/script.json"); + var stringContent = new StringContent(content, Encoding.UTF8, "application/json"); + + // Act + HttpResponseMessage response = await Client.PostAsync("/api/v2/scripts", stringContent); + + // Assert + response.EnsureSuccessStatusCode(); + } + + [Test] + public async Task PostRawEvent_ReturnsOk() + { + // Arrange + var content = await File.ReadAllTextAsync("assets/event.json"); + var stringContent = new StringContent(content, Encoding.UTF8, "application/json"); + + // Act + HttpResponseMessage response = await Client.PostAsync("/api/v2/events", stringContent); + + // Assert + response.EnsureSuccessStatusCode(); + } } } \ No newline at end of file diff --git a/tests/Telemetry.Api.IntegrationTests/Telemetry.Api.IntegrationTests.csproj b/tests/Telemetry.Api.IntegrationTests/Telemetry.Api.IntegrationTests.csproj index aee3e7f..7f339ab 100644 --- a/tests/Telemetry.Api.IntegrationTests/Telemetry.Api.IntegrationTests.csproj +++ b/tests/Telemetry.Api.IntegrationTests/Telemetry.Api.IntegrationTests.csproj @@ -25,8 +25,4 @@ - - - - diff --git a/tests/Telemetry.Api.IntegrationTests/assets/event.json b/tests/Telemetry.Api.IntegrationTests/assets/event.json new file mode 100644 index 0000000..a04d2ef --- /dev/null +++ b/tests/Telemetry.Api.IntegrationTests/assets/event.json @@ -0,0 +1,27 @@ +{ + "handler_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", + "meta": { + "schema": "2.0.0" + }, + "type": "AppStartup", + "status": "success", + "timestamp": "2024-03-27T10:00:00Z", + "username": "testuser", + "host_user": "ad\\testuser", + "revitbuild": "2024.1", + "revit": "Revit 2024", + "cancelled": false, + "docid": 42, + "doctype": "doc type", + "doctemplate": "doc template", + "docname": "doc name", + "docpath": "C:\\doc.rvt", + "projectname": "doc.rvt", + "projectnum": "projectnum", + "args": { + "operation": "transaction", + "added": 1, + "deleted": 2, + "modified": 4 + } +} \ No newline at end of file diff --git a/tests/Telemetry.Api.IntegrationTests/assets/script.json b/tests/Telemetry.Api.IntegrationTests/assets/script.json new file mode 100644 index 0000000..d050e3f --- /dev/null +++ b/tests/Telemetry.Api.IntegrationTests/assets/script.json @@ -0,0 +1,48 @@ +{ + "sessionId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", + "meta": { + "schema": "2.0.0" + }, + "timestamp": "2024-03-27T10:00:00Z", + "username": "testuser", + "host_user": "ad\\testuser", + "revitBuild": "2024.1", + "revit": "Revit 2024", + "pyrevit": "4.8.12", + "clone": "master", + "debug": false, + "config": true, + "from_gui": true, + "exec_id": "exec-123", + "exec_timestamp": "2024-03-27T10:00:05Z", + "commandbundle": "bundle-xyz", + "commandextension": "ext-abc", + "commandname": "TestCommand", + "commanduniquename": "TestUniqueName", + "scriptpath": "C:/scripts/test.py", + "trace": { + "message": "Script executed successfully", + "engine": { + "type": "IronPython", + "version": "2.7.12", + "sysPath": [ + "path1", + "path2" + ], + "configs": { + "config": 1, + "version": 12, + "some_object": { + "hey": "hey" + }, + "some_array": [ + 1, + 2, + 3, + 4 + ] + } + } + }, + "commandresults": {} +} \ No newline at end of file From 11e85fff5155bc01783a73ba4e930f16381c7314 Mon Sep 17 00:00:00 2001 From: dosymep Date: Mon, 6 Apr 2026 16:24:27 +0600 Subject: [PATCH 18/31] add new migrations --- .../Persistence/ApplicationDbContext.cs | 30 +- ...101958_UpdateDynamicDataOracle.Designer.cs | 321 ++++++++++++++++++ .../20260406101958_UpdateDynamicDataOracle.cs | 90 +++++ .../ApplicationDbContextModelSnapshot.cs | 143 +++++--- ...2030_UpdateDynamicDataPostgres.Designer.cs | 321 ++++++++++++++++++ ...0260406102030_UpdateDynamicDataPostgres.cs | 90 +++++ .../ApplicationDbContextModelSnapshot.cs | 143 +++++--- ...100_UpdateDynamicDataSqlServer.Designer.cs | 321 ++++++++++++++++++ ...260406102100_UpdateDynamicDataSqlServer.cs | 90 +++++ .../ApplicationDbContextModelSnapshot.cs | 143 +++++--- ...102040_UpdateDynamicDataSqlite.Designer.cs | 316 +++++++++++++++++ .../20260406102040_UpdateDynamicDataSqlite.cs | 90 +++++ .../ApplicationDbContextModelSnapshot.cs | 143 +++++--- 13 files changed, 2046 insertions(+), 195 deletions(-) create mode 100644 src/Telemetry.Migrations.Oracle/Migrations/20260406101958_UpdateDynamicDataOracle.Designer.cs create mode 100644 src/Telemetry.Migrations.Oracle/Migrations/20260406101958_UpdateDynamicDataOracle.cs create mode 100644 src/Telemetry.Migrations.Postgres/Migrations/20260406102030_UpdateDynamicDataPostgres.Designer.cs create mode 100644 src/Telemetry.Migrations.Postgres/Migrations/20260406102030_UpdateDynamicDataPostgres.cs create mode 100644 src/Telemetry.Migrations.SqlServer/Migrations/20260406102100_UpdateDynamicDataSqlServer.Designer.cs create mode 100644 src/Telemetry.Migrations.SqlServer/Migrations/20260406102100_UpdateDynamicDataSqlServer.cs create mode 100644 src/Telemetry.Migrations.Sqlite/Migrations/20260406102040_UpdateDynamicDataSqlite.Designer.cs create mode 100644 src/Telemetry.Migrations.Sqlite/Migrations/20260406102040_UpdateDynamicDataSqlite.cs diff --git a/src/Telemetry.Api/Infrastructure/Persistence/ApplicationDbContext.cs b/src/Telemetry.Api/Infrastructure/Persistence/ApplicationDbContext.cs index a7f2f08..dfeae5c 100644 --- a/src/Telemetry.Api/Infrastructure/Persistence/ApplicationDbContext.cs +++ b/src/Telemetry.Api/Infrastructure/Persistence/ApplicationDbContext.cs @@ -151,8 +151,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) entity.Property(e => e.Timestamp) .HasColumnName("timestamp") - .HasElementName("timestamp") - .HasBsonRepresentation(BsonType.DateTime); + .HasElementName("timestamp"); entity.Property(e => e.Username) .HasColumnName("username") @@ -196,8 +195,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) entity.Property(e => e.ExecTimestamp) .HasColumnName("exec_timestamp") - .HasElementName("exec_timestamp") - .HasBsonRepresentation(BsonType.DateTime); + .HasElementName("exec_timestamp"); entity.Property(e => e.CommandBundle) .HasColumnName("commandbundle") @@ -215,7 +213,8 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) .HasColumnName("commanduniquename") .HasElementName("commanduniquename"); - entity.Property(e => e.DocumentName).HasColumnName("docname") + entity.Property(e => e.DocumentName) + .HasColumnName("docname") .HasElementName("docname"); entity.Property(e => e.DocumentPath) @@ -273,8 +272,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) entity.Property(e => e.Timestamp) .HasColumnName("timestamp") - .HasElementName("timestamp") - .HasBsonRepresentation(BsonType.DateTime); + .HasElementName("timestamp"); entity.Property(e => e.Username) .HasColumnName("username") @@ -340,6 +338,24 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) v => JsonSerializer.Deserialize(v, JsonSerializerOptions.Web)!); }); + if (Database.ProviderName!.Equals("MongoDB.EntityFrameworkCore")) + { + modelBuilder.Entity(entity => + { + entity.Property(e => e.Timestamp) + .HasBsonRepresentation(BsonType.DateTime); + + entity.Property(e => e.ExecTimestamp) + .HasBsonRepresentation(BsonType.DateTime); + }); + + modelBuilder.Entity(entity => + { + entity.Property(e => e.Timestamp) + .HasBsonRepresentation(BsonType.DateTime); + }); + } + base.OnModelCreating(modelBuilder); } } diff --git a/src/Telemetry.Migrations.Oracle/Migrations/20260406101958_UpdateDynamicDataOracle.Designer.cs b/src/Telemetry.Migrations.Oracle/Migrations/20260406101958_UpdateDynamicDataOracle.Designer.cs new file mode 100644 index 0000000..08069d2 --- /dev/null +++ b/src/Telemetry.Migrations.Oracle/Migrations/20260406101958_UpdateDynamicDataOracle.Designer.cs @@ -0,0 +1,321 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Oracle.EntityFrameworkCore.Metadata; +using Telemetry.Api.Infrastructure.Persistence; + +#nullable disable + +namespace Telemetry.Migrations.Oracle.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20260406101958_UpdateDynamicDataOracle")] + partial class UpdateDynamicDataOracle + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "10.0.5") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + OracleModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Telemetry.Api.Domain.Models.EventRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("RAW(16)") + .HasColumnName("_id") + .HasAnnotation("Mongo:ElementName", "_id"); + + b.Property("Cancellable") + .HasColumnType("BOOLEAN") + .HasColumnName("cancellable") + .HasAnnotation("Mongo:ElementName", "cancellable"); + + b.Property("Cancelled") + .HasColumnType("BOOLEAN") + .HasColumnName("cancelled") + .HasAnnotation("Mongo:ElementName", "cancelled"); + + b.Property("DocumentId") + .HasColumnType("NUMBER(10)") + .HasColumnName("docid") + .HasAnnotation("Mongo:ElementName", "docid"); + + b.Property("DocumentName") + .HasMaxLength(250) + .HasColumnType("NVARCHAR2(250)") + .HasColumnName("docname") + .HasAnnotation("Mongo:ElementName", "docname"); + + b.Property("DocumentPath") + .HasMaxLength(1024) + .HasColumnType("NVARCHAR2(1024)") + .HasColumnName("docpath") + .HasAnnotation("Mongo:ElementName", "docpath"); + + b.Property("DocumentTemplate") + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("doctemplate") + .HasAnnotation("Mongo:ElementName", "doctemplate"); + + b.Property("DocumentType") + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("doctype") + .HasAnnotation("Mongo:ElementName", "doctype"); + + b.Property("EventArgs") + .HasMaxLength(8000) + .HasColumnType("NCLOB") + .HasColumnName("args") + .HasAnnotation("Mongo:ElementName", "args"); + + b.Property("EventType") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("type") + .HasAnnotation("Mongo:ElementName", "type"); + + b.Property("HandlerId") + .HasColumnType("RAW(16)") + .HasColumnName("handler_id") + .HasAnnotation("Mongo:ElementName", "handler_id"); + + b.Property("HostUsername") + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("host_user") + .HasAnnotation("Mongo:ElementName", "host_user"); + + b.Property("Meta") + .IsRequired() + .HasColumnType("NVARCHAR2(2000)") + .HasColumnName("meta") + .HasAnnotation("Mongo:ElementName", "meta"); + + b.Property("ProjectName") + .HasMaxLength(250) + .HasColumnType("NVARCHAR2(250)") + .HasColumnName("projectname") + .HasAnnotation("Mongo:ElementName", "projectname"); + + b.Property("ProjectNum") + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("projectnum") + .HasAnnotation("Mongo:ElementName", "projectnum"); + + b.Property("RevitBuild") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("revitbuild") + .HasAnnotation("Mongo:ElementName", "revitbuild"); + + b.Property("RevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("revit") + .HasAnnotation("Mongo:ElementName", "revit"); + + b.Property("Status") + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("status") + .HasAnnotation("Mongo:ElementName", "status"); + + b.Property("Timestamp") + .HasColumnType("TIMESTAMP(7) WITH TIME ZONE") + .HasColumnName("timestamp") + .HasAnnotation("Mongo:ElementName", "timestamp"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("username") + .HasAnnotation("Mongo:ElementName", "username"); + + b.HasKey("Id"); + + b.ToTable("events", (string)null); + + b.HasAnnotation("Mongo:CollectionName", "events"); + }); + + modelBuilder.Entity("Telemetry.Api.Domain.Models.ScriptRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("RAW(16)") + .HasColumnName("_id") + .HasAnnotation("Mongo:ElementName", "_id"); + + b.Property("CloneName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("clone") + .HasAnnotation("Mongo:ElementName", "clone"); + + b.Property("CommandBundle") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("NVARCHAR2(250)") + .HasColumnName("commandbundle") + .HasAnnotation("Mongo:ElementName", "commandbundle"); + + b.Property("CommandExtension") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("NVARCHAR2(250)") + .HasColumnName("commandextension") + .HasAnnotation("Mongo:ElementName", "commandextension"); + + b.Property("CommandName") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("NVARCHAR2(250)") + .HasColumnName("commandname") + .HasAnnotation("Mongo:ElementName", "commandname"); + + b.Property("CommandResults") + .HasMaxLength(8000) + .HasColumnType("NCLOB") + .HasColumnName("commandresults") + .HasAnnotation("Mongo:ElementName", "commandresults"); + + b.Property("CommandUniqueName") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("NVARCHAR2(500)") + .HasColumnName("commanduniquename") + .HasAnnotation("Mongo:ElementName", "commanduniquename"); + + b.Property("DocumentName") + .HasMaxLength(250) + .HasColumnType("NVARCHAR2(250)") + .HasColumnName("docname") + .HasAnnotation("Mongo:ElementName", "docname"); + + b.Property("DocumentPath") + .HasMaxLength(1024) + .HasColumnType("NVARCHAR2(1024)") + .HasColumnName("docpath") + .HasAnnotation("Mongo:ElementName", "docpath"); + + b.Property("ExecId") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("exec_id") + .HasAnnotation("Mongo:ElementName", "exec_id"); + + b.Property("ExecTimestamp") + .HasColumnType("TIMESTAMP(7) WITH TIME ZONE") + .HasColumnName("exec_timestamp") + .HasAnnotation("Mongo:ElementName", "exec_timestamp"); + + b.Property("HostUsername") + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("host_user") + .HasAnnotation("Mongo:ElementName", "host_user"); + + b.Property("IsConfig") + .HasColumnType("BOOLEAN") + .HasColumnName("config") + .HasAnnotation("Mongo:ElementName", "config"); + + b.Property("IsDebug") + .HasColumnType("BOOLEAN") + .HasColumnName("debug") + .HasAnnotation("Mongo:ElementName", "debug"); + + b.Property("IsExecFromGui") + .HasColumnType("BOOLEAN") + .HasColumnName("from_gui") + .HasAnnotation("Mongo:ElementName", "from_gui"); + + b.Property("Meta") + .IsRequired() + .HasColumnType("NVARCHAR2(2000)") + .HasColumnName("meta") + .HasAnnotation("Mongo:ElementName", "meta"); + + b.Property("PyRevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("pyrevit") + .HasAnnotation("Mongo:ElementName", "pyrevit"); + + b.Property("ResultCode") + .HasColumnType("NUMBER(10)") + .HasColumnName("resultcode") + .HasAnnotation("Mongo:ElementName", "resultcode"); + + b.Property("RevitBuild") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("revitbuild") + .HasAnnotation("Mongo:ElementName", "revitbuild"); + + b.Property("RevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("revit") + .HasAnnotation("Mongo:ElementName", "revit"); + + b.Property("ScriptPath") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("NVARCHAR2(1024)") + .HasColumnName("scriptpath") + .HasAnnotation("Mongo:ElementName", "scriptpath"); + + b.Property("SessionId") + .HasColumnType("RAW(16)") + .HasColumnName("sessionid") + .HasAnnotation("Mongo:ElementName", "sessionid"); + + b.Property("Timestamp") + .HasColumnType("TIMESTAMP(7) WITH TIME ZONE") + .HasColumnName("timestamp") + .HasAnnotation("Mongo:ElementName", "timestamp"); + + b.Property("Trace") + .IsRequired() + .HasColumnType("NVARCHAR2(2000)") + .HasColumnName("trace") + .HasAnnotation("Mongo:ElementName", "trace"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("username") + .HasAnnotation("Mongo:ElementName", "username"); + + b.HasKey("Id"); + + b.ToTable("scripts", (string)null); + + b.HasAnnotation("Mongo:CollectionName", "scripts"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Telemetry.Migrations.Oracle/Migrations/20260406101958_UpdateDynamicDataOracle.cs b/src/Telemetry.Migrations.Oracle/Migrations/20260406101958_UpdateDynamicDataOracle.cs new file mode 100644 index 0000000..8867cc0 --- /dev/null +++ b/src/Telemetry.Migrations.Oracle/Migrations/20260406101958_UpdateDynamicDataOracle.cs @@ -0,0 +1,90 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Telemetry.Migrations.Oracle.Migrations +{ + /// + public partial class UpdateDynamicDataOracle : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropPrimaryKey( + name: "PK_script_record", + table: "script_record"); + + migrationBuilder.DropPrimaryKey( + name: "PK_event_record", + table: "event_record"); + + migrationBuilder.RenameTable( + name: "script_record", + newName: "scripts"); + + migrationBuilder.RenameTable( + name: "event_record", + newName: "events"); + + migrationBuilder.RenameColumn( + name: "id", + table: "scripts", + newName: "_id"); + + migrationBuilder.RenameColumn( + name: "id", + table: "events", + newName: "_id"); + + migrationBuilder.AddPrimaryKey( + name: "PK_scripts", + table: "scripts", + column: "_id"); + + migrationBuilder.AddPrimaryKey( + name: "PK_events", + table: "events", + column: "_id"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropPrimaryKey( + name: "PK_scripts", + table: "scripts"); + + migrationBuilder.DropPrimaryKey( + name: "PK_events", + table: "events"); + + migrationBuilder.RenameTable( + name: "scripts", + newName: "script_record"); + + migrationBuilder.RenameTable( + name: "events", + newName: "event_record"); + + migrationBuilder.RenameColumn( + name: "_id", + table: "script_record", + newName: "id"); + + migrationBuilder.RenameColumn( + name: "_id", + table: "event_record", + newName: "id"); + + migrationBuilder.AddPrimaryKey( + name: "PK_script_record", + table: "script_record", + column: "id"); + + migrationBuilder.AddPrimaryKey( + name: "PK_event_record", + table: "event_record", + column: "id"); + } + } +} diff --git a/src/Telemetry.Migrations.Oracle/Migrations/ApplicationDbContextModelSnapshot.cs b/src/Telemetry.Migrations.Oracle/Migrations/ApplicationDbContextModelSnapshot.cs index 56dca43..af1ac4b 100644 --- a/src/Telemetry.Migrations.Oracle/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/src/Telemetry.Migrations.Oracle/Migrations/ApplicationDbContextModelSnapshot.cs @@ -27,105 +27,127 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("RAW(16)") - .HasColumnName("id"); + .HasColumnName("_id") + .HasAnnotation("Mongo:ElementName", "_id"); b.Property("Cancellable") .HasColumnType("BOOLEAN") - .HasColumnName("cancellable"); + .HasColumnName("cancellable") + .HasAnnotation("Mongo:ElementName", "cancellable"); b.Property("Cancelled") .HasColumnType("BOOLEAN") - .HasColumnName("cancelled"); + .HasColumnName("cancelled") + .HasAnnotation("Mongo:ElementName", "cancelled"); b.Property("DocumentId") .HasColumnType("NUMBER(10)") - .HasColumnName("docid"); + .HasColumnName("docid") + .HasAnnotation("Mongo:ElementName", "docid"); b.Property("DocumentName") .HasMaxLength(250) .HasColumnType("NVARCHAR2(250)") - .HasColumnName("docname"); + .HasColumnName("docname") + .HasAnnotation("Mongo:ElementName", "docname"); b.Property("DocumentPath") .HasMaxLength(1024) .HasColumnType("NVARCHAR2(1024)") - .HasColumnName("docpath"); + .HasColumnName("docpath") + .HasAnnotation("Mongo:ElementName", "docpath"); b.Property("DocumentTemplate") .HasMaxLength(100) .HasColumnType("NVARCHAR2(100)") - .HasColumnName("doctemplate"); + .HasColumnName("doctemplate") + .HasAnnotation("Mongo:ElementName", "doctemplate"); b.Property("DocumentType") .HasMaxLength(100) .HasColumnType("NVARCHAR2(100)") - .HasColumnName("doctype"); + .HasColumnName("doctype") + .HasAnnotation("Mongo:ElementName", "doctype"); b.Property("EventArgs") .HasMaxLength(8000) .HasColumnType("NCLOB") - .HasColumnName("args"); + .HasColumnName("args") + .HasAnnotation("Mongo:ElementName", "args"); b.Property("EventType") .IsRequired() .HasMaxLength(100) .HasColumnType("NVARCHAR2(100)") - .HasColumnName("type"); + .HasColumnName("type") + .HasAnnotation("Mongo:ElementName", "type"); b.Property("HandlerId") .HasColumnType("RAW(16)") - .HasColumnName("handler_id"); + .HasColumnName("handler_id") + .HasAnnotation("Mongo:ElementName", "handler_id"); b.Property("HostUsername") .HasMaxLength(100) .HasColumnType("NVARCHAR2(100)") - .HasColumnName("host_user"); + .HasColumnName("host_user") + .HasAnnotation("Mongo:ElementName", "host_user"); b.Property("Meta") .IsRequired() .HasColumnType("NVARCHAR2(2000)") - .HasColumnName("meta"); + .HasColumnName("meta") + .HasAnnotation("Mongo:ElementName", "meta"); b.Property("ProjectName") .HasMaxLength(250) .HasColumnType("NVARCHAR2(250)") - .HasColumnName("projectname"); + .HasColumnName("projectname") + .HasAnnotation("Mongo:ElementName", "projectname"); b.Property("ProjectNum") .HasMaxLength(100) .HasColumnType("NVARCHAR2(100)") - .HasColumnName("projectnum"); + .HasColumnName("projectnum") + .HasAnnotation("Mongo:ElementName", "projectnum"); b.Property("RevitBuild") .IsRequired() .HasMaxLength(100) .HasColumnType("NVARCHAR2(100)") - .HasColumnName("revitbuild"); + .HasColumnName("revitbuild") + .HasAnnotation("Mongo:ElementName", "revitbuild"); b.Property("RevitVersion") .IsRequired() .HasMaxLength(100) .HasColumnType("NVARCHAR2(100)") - .HasColumnName("revit"); + .HasColumnName("revit") + .HasAnnotation("Mongo:ElementName", "revit"); b.Property("Status") .HasMaxLength(100) .HasColumnType("NVARCHAR2(100)") - .HasColumnName("status"); + .HasColumnName("status") + .HasAnnotation("Mongo:ElementName", "status"); b.Property("Timestamp") .HasColumnType("TIMESTAMP(7) WITH TIME ZONE") - .HasColumnName("timestamp"); + .HasColumnName("timestamp") + .HasAnnotation("Mongo:ElementName", "timestamp"); b.Property("Username") .IsRequired() .HasMaxLength(100) .HasColumnType("NVARCHAR2(100)") - .HasColumnName("username"); + .HasColumnName("username") + .HasAnnotation("Mongo:ElementName", "username"); b.HasKey("Id"); - b.ToTable("event_record", (string)null); + b.ToTable("events", (string)null); + + b.HasAnnotation("Mongo:CollectionName", "events"); }); modelBuilder.Entity("Telemetry.Api.Domain.Models.ScriptRecord", b => @@ -133,135 +155,162 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("RAW(16)") - .HasColumnName("id"); + .HasColumnName("_id") + .HasAnnotation("Mongo:ElementName", "_id"); b.Property("CloneName") .IsRequired() .HasMaxLength(100) .HasColumnType("NVARCHAR2(100)") - .HasColumnName("clone"); + .HasColumnName("clone") + .HasAnnotation("Mongo:ElementName", "clone"); b.Property("CommandBundle") .IsRequired() .HasMaxLength(250) .HasColumnType("NVARCHAR2(250)") - .HasColumnName("commandbundle"); + .HasColumnName("commandbundle") + .HasAnnotation("Mongo:ElementName", "commandbundle"); b.Property("CommandExtension") .IsRequired() .HasMaxLength(250) .HasColumnType("NVARCHAR2(250)") - .HasColumnName("commandextension"); + .HasColumnName("commandextension") + .HasAnnotation("Mongo:ElementName", "commandextension"); b.Property("CommandName") .IsRequired() .HasMaxLength(250) .HasColumnType("NVARCHAR2(250)") - .HasColumnName("commandname"); + .HasColumnName("commandname") + .HasAnnotation("Mongo:ElementName", "commandname"); b.Property("CommandResults") .HasMaxLength(8000) .HasColumnType("NCLOB") - .HasColumnName("commandresults"); + .HasColumnName("commandresults") + .HasAnnotation("Mongo:ElementName", "commandresults"); b.Property("CommandUniqueName") .IsRequired() .HasMaxLength(500) .HasColumnType("NVARCHAR2(500)") - .HasColumnName("commanduniquename"); + .HasColumnName("commanduniquename") + .HasAnnotation("Mongo:ElementName", "commanduniquename"); b.Property("DocumentName") .HasMaxLength(250) .HasColumnType("NVARCHAR2(250)") - .HasColumnName("docname"); + .HasColumnName("docname") + .HasAnnotation("Mongo:ElementName", "docname"); b.Property("DocumentPath") .HasMaxLength(1024) .HasColumnType("NVARCHAR2(1024)") - .HasColumnName("docpath"); + .HasColumnName("docpath") + .HasAnnotation("Mongo:ElementName", "docpath"); b.Property("ExecId") .IsRequired() .HasMaxLength(100) .HasColumnType("NVARCHAR2(100)") - .HasColumnName("exec_id"); + .HasColumnName("exec_id") + .HasAnnotation("Mongo:ElementName", "exec_id"); b.Property("ExecTimestamp") .HasColumnType("TIMESTAMP(7) WITH TIME ZONE") - .HasColumnName("exec_timestamp"); + .HasColumnName("exec_timestamp") + .HasAnnotation("Mongo:ElementName", "exec_timestamp"); b.Property("HostUsername") .HasMaxLength(100) .HasColumnType("NVARCHAR2(100)") - .HasColumnName("host_user"); + .HasColumnName("host_user") + .HasAnnotation("Mongo:ElementName", "host_user"); b.Property("IsConfig") .HasColumnType("BOOLEAN") - .HasColumnName("config"); + .HasColumnName("config") + .HasAnnotation("Mongo:ElementName", "config"); b.Property("IsDebug") .HasColumnType("BOOLEAN") - .HasColumnName("debug"); + .HasColumnName("debug") + .HasAnnotation("Mongo:ElementName", "debug"); b.Property("IsExecFromGui") .HasColumnType("BOOLEAN") - .HasColumnName("from_gui"); + .HasColumnName("from_gui") + .HasAnnotation("Mongo:ElementName", "from_gui"); b.Property("Meta") .IsRequired() .HasColumnType("NVARCHAR2(2000)") - .HasColumnName("meta"); + .HasColumnName("meta") + .HasAnnotation("Mongo:ElementName", "meta"); b.Property("PyRevitVersion") .IsRequired() .HasMaxLength(100) .HasColumnType("NVARCHAR2(100)") - .HasColumnName("pyrevit"); + .HasColumnName("pyrevit") + .HasAnnotation("Mongo:ElementName", "pyrevit"); b.Property("ResultCode") .HasColumnType("NUMBER(10)") - .HasColumnName("resultcode"); + .HasColumnName("resultcode") + .HasAnnotation("Mongo:ElementName", "resultcode"); b.Property("RevitBuild") .IsRequired() .HasMaxLength(100) .HasColumnType("NVARCHAR2(100)") - .HasColumnName("revitbuild"); + .HasColumnName("revitbuild") + .HasAnnotation("Mongo:ElementName", "revitbuild"); b.Property("RevitVersion") .IsRequired() .HasMaxLength(100) .HasColumnType("NVARCHAR2(100)") - .HasColumnName("revit"); + .HasColumnName("revit") + .HasAnnotation("Mongo:ElementName", "revit"); b.Property("ScriptPath") .IsRequired() .HasMaxLength(1024) .HasColumnType("NVARCHAR2(1024)") - .HasColumnName("scriptpath"); + .HasColumnName("scriptpath") + .HasAnnotation("Mongo:ElementName", "scriptpath"); b.Property("SessionId") .HasColumnType("RAW(16)") - .HasColumnName("sessionid"); + .HasColumnName("sessionid") + .HasAnnotation("Mongo:ElementName", "sessionid"); b.Property("Timestamp") .HasColumnType("TIMESTAMP(7) WITH TIME ZONE") - .HasColumnName("timestamp"); + .HasColumnName("timestamp") + .HasAnnotation("Mongo:ElementName", "timestamp"); b.Property("Trace") .IsRequired() .HasColumnType("NVARCHAR2(2000)") - .HasColumnName("trace"); + .HasColumnName("trace") + .HasAnnotation("Mongo:ElementName", "trace"); b.Property("Username") .IsRequired() .HasMaxLength(100) .HasColumnType("NVARCHAR2(100)") - .HasColumnName("username"); + .HasColumnName("username") + .HasAnnotation("Mongo:ElementName", "username"); b.HasKey("Id"); - b.ToTable("script_record", (string)null); + b.ToTable("scripts", (string)null); + + b.HasAnnotation("Mongo:CollectionName", "scripts"); }); #pragma warning restore 612, 618 } diff --git a/src/Telemetry.Migrations.Postgres/Migrations/20260406102030_UpdateDynamicDataPostgres.Designer.cs b/src/Telemetry.Migrations.Postgres/Migrations/20260406102030_UpdateDynamicDataPostgres.Designer.cs new file mode 100644 index 0000000..3689a96 --- /dev/null +++ b/src/Telemetry.Migrations.Postgres/Migrations/20260406102030_UpdateDynamicDataPostgres.Designer.cs @@ -0,0 +1,321 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using Telemetry.Api.Infrastructure.Persistence; + +#nullable disable + +namespace Telemetry.Migrations.Postgres.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20260406102030_UpdateDynamicDataPostgres")] + partial class UpdateDynamicDataPostgres + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "10.0.5") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Telemetry.Api.Domain.Models.EventRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("_id") + .HasAnnotation("Mongo:ElementName", "_id"); + + b.Property("Cancellable") + .HasColumnType("boolean") + .HasColumnName("cancellable") + .HasAnnotation("Mongo:ElementName", "cancellable"); + + b.Property("Cancelled") + .HasColumnType("boolean") + .HasColumnName("cancelled") + .HasAnnotation("Mongo:ElementName", "cancelled"); + + b.Property("DocumentId") + .HasColumnType("integer") + .HasColumnName("docid") + .HasAnnotation("Mongo:ElementName", "docid"); + + b.Property("DocumentName") + .HasMaxLength(250) + .HasColumnType("character varying(250)") + .HasColumnName("docname") + .HasAnnotation("Mongo:ElementName", "docname"); + + b.Property("DocumentPath") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("docpath") + .HasAnnotation("Mongo:ElementName", "docpath"); + + b.Property("DocumentTemplate") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("doctemplate") + .HasAnnotation("Mongo:ElementName", "doctemplate"); + + b.Property("DocumentType") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("doctype") + .HasAnnotation("Mongo:ElementName", "doctype"); + + b.Property("EventArgs") + .HasMaxLength(8000) + .HasColumnType("character varying(8000)") + .HasColumnName("args") + .HasAnnotation("Mongo:ElementName", "args"); + + b.Property("EventType") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("type") + .HasAnnotation("Mongo:ElementName", "type"); + + b.Property("HandlerId") + .HasColumnType("uuid") + .HasColumnName("handler_id") + .HasAnnotation("Mongo:ElementName", "handler_id"); + + b.Property("HostUsername") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("host_user") + .HasAnnotation("Mongo:ElementName", "host_user"); + + b.Property("Meta") + .IsRequired() + .HasColumnType("text") + .HasColumnName("meta") + .HasAnnotation("Mongo:ElementName", "meta"); + + b.Property("ProjectName") + .HasMaxLength(250) + .HasColumnType("character varying(250)") + .HasColumnName("projectname") + .HasAnnotation("Mongo:ElementName", "projectname"); + + b.Property("ProjectNum") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("projectnum") + .HasAnnotation("Mongo:ElementName", "projectnum"); + + b.Property("RevitBuild") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("revitbuild") + .HasAnnotation("Mongo:ElementName", "revitbuild"); + + b.Property("RevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("revit") + .HasAnnotation("Mongo:ElementName", "revit"); + + b.Property("Status") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("status") + .HasAnnotation("Mongo:ElementName", "status"); + + b.Property("Timestamp") + .HasColumnType("timestamp with time zone") + .HasColumnName("timestamp") + .HasAnnotation("Mongo:ElementName", "timestamp"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("username") + .HasAnnotation("Mongo:ElementName", "username"); + + b.HasKey("Id"); + + b.ToTable("events", (string)null); + + b.HasAnnotation("Mongo:CollectionName", "events"); + }); + + modelBuilder.Entity("Telemetry.Api.Domain.Models.ScriptRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("_id") + .HasAnnotation("Mongo:ElementName", "_id"); + + b.Property("CloneName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("clone") + .HasAnnotation("Mongo:ElementName", "clone"); + + b.Property("CommandBundle") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)") + .HasColumnName("commandbundle") + .HasAnnotation("Mongo:ElementName", "commandbundle"); + + b.Property("CommandExtension") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)") + .HasColumnName("commandextension") + .HasAnnotation("Mongo:ElementName", "commandextension"); + + b.Property("CommandName") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)") + .HasColumnName("commandname") + .HasAnnotation("Mongo:ElementName", "commandname"); + + b.Property("CommandResults") + .HasMaxLength(8000) + .HasColumnType("character varying(8000)") + .HasColumnName("commandresults") + .HasAnnotation("Mongo:ElementName", "commandresults"); + + b.Property("CommandUniqueName") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("character varying(500)") + .HasColumnName("commanduniquename") + .HasAnnotation("Mongo:ElementName", "commanduniquename"); + + b.Property("DocumentName") + .HasMaxLength(250) + .HasColumnType("character varying(250)") + .HasColumnName("docname") + .HasAnnotation("Mongo:ElementName", "docname"); + + b.Property("DocumentPath") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("docpath") + .HasAnnotation("Mongo:ElementName", "docpath"); + + b.Property("ExecId") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("exec_id") + .HasAnnotation("Mongo:ElementName", "exec_id"); + + b.Property("ExecTimestamp") + .HasColumnType("timestamp with time zone") + .HasColumnName("exec_timestamp") + .HasAnnotation("Mongo:ElementName", "exec_timestamp"); + + b.Property("HostUsername") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("host_user") + .HasAnnotation("Mongo:ElementName", "host_user"); + + b.Property("IsConfig") + .HasColumnType("boolean") + .HasColumnName("config") + .HasAnnotation("Mongo:ElementName", "config"); + + b.Property("IsDebug") + .HasColumnType("boolean") + .HasColumnName("debug") + .HasAnnotation("Mongo:ElementName", "debug"); + + b.Property("IsExecFromGui") + .HasColumnType("boolean") + .HasColumnName("from_gui") + .HasAnnotation("Mongo:ElementName", "from_gui"); + + b.Property("Meta") + .IsRequired() + .HasColumnType("text") + .HasColumnName("meta") + .HasAnnotation("Mongo:ElementName", "meta"); + + b.Property("PyRevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("pyrevit") + .HasAnnotation("Mongo:ElementName", "pyrevit"); + + b.Property("ResultCode") + .HasColumnType("integer") + .HasColumnName("resultcode") + .HasAnnotation("Mongo:ElementName", "resultcode"); + + b.Property("RevitBuild") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("revitbuild") + .HasAnnotation("Mongo:ElementName", "revitbuild"); + + b.Property("RevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("revit") + .HasAnnotation("Mongo:ElementName", "revit"); + + b.Property("ScriptPath") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("scriptpath") + .HasAnnotation("Mongo:ElementName", "scriptpath"); + + b.Property("SessionId") + .HasColumnType("uuid") + .HasColumnName("sessionid") + .HasAnnotation("Mongo:ElementName", "sessionid"); + + b.Property("Timestamp") + .HasColumnType("timestamp with time zone") + .HasColumnName("timestamp") + .HasAnnotation("Mongo:ElementName", "timestamp"); + + b.Property("Trace") + .IsRequired() + .HasColumnType("text") + .HasColumnName("trace") + .HasAnnotation("Mongo:ElementName", "trace"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("username") + .HasAnnotation("Mongo:ElementName", "username"); + + b.HasKey("Id"); + + b.ToTable("scripts", (string)null); + + b.HasAnnotation("Mongo:CollectionName", "scripts"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Telemetry.Migrations.Postgres/Migrations/20260406102030_UpdateDynamicDataPostgres.cs b/src/Telemetry.Migrations.Postgres/Migrations/20260406102030_UpdateDynamicDataPostgres.cs new file mode 100644 index 0000000..420ea71 --- /dev/null +++ b/src/Telemetry.Migrations.Postgres/Migrations/20260406102030_UpdateDynamicDataPostgres.cs @@ -0,0 +1,90 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Telemetry.Migrations.Postgres.Migrations +{ + /// + public partial class UpdateDynamicDataPostgres : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropPrimaryKey( + name: "PK_script_record", + table: "script_record"); + + migrationBuilder.DropPrimaryKey( + name: "PK_event_record", + table: "event_record"); + + migrationBuilder.RenameTable( + name: "script_record", + newName: "scripts"); + + migrationBuilder.RenameTable( + name: "event_record", + newName: "events"); + + migrationBuilder.RenameColumn( + name: "id", + table: "scripts", + newName: "_id"); + + migrationBuilder.RenameColumn( + name: "id", + table: "events", + newName: "_id"); + + migrationBuilder.AddPrimaryKey( + name: "PK_scripts", + table: "scripts", + column: "_id"); + + migrationBuilder.AddPrimaryKey( + name: "PK_events", + table: "events", + column: "_id"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropPrimaryKey( + name: "PK_scripts", + table: "scripts"); + + migrationBuilder.DropPrimaryKey( + name: "PK_events", + table: "events"); + + migrationBuilder.RenameTable( + name: "scripts", + newName: "script_record"); + + migrationBuilder.RenameTable( + name: "events", + newName: "event_record"); + + migrationBuilder.RenameColumn( + name: "_id", + table: "script_record", + newName: "id"); + + migrationBuilder.RenameColumn( + name: "_id", + table: "event_record", + newName: "id"); + + migrationBuilder.AddPrimaryKey( + name: "PK_script_record", + table: "script_record", + column: "id"); + + migrationBuilder.AddPrimaryKey( + name: "PK_event_record", + table: "event_record", + column: "id"); + } + } +} diff --git a/src/Telemetry.Migrations.Postgres/Migrations/ApplicationDbContextModelSnapshot.cs b/src/Telemetry.Migrations.Postgres/Migrations/ApplicationDbContextModelSnapshot.cs index 35a3fd4..d18a3cb 100644 --- a/src/Telemetry.Migrations.Postgres/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/src/Telemetry.Migrations.Postgres/Migrations/ApplicationDbContextModelSnapshot.cs @@ -27,105 +27,127 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("uuid") - .HasColumnName("id"); + .HasColumnName("_id") + .HasAnnotation("Mongo:ElementName", "_id"); b.Property("Cancellable") .HasColumnType("boolean") - .HasColumnName("cancellable"); + .HasColumnName("cancellable") + .HasAnnotation("Mongo:ElementName", "cancellable"); b.Property("Cancelled") .HasColumnType("boolean") - .HasColumnName("cancelled"); + .HasColumnName("cancelled") + .HasAnnotation("Mongo:ElementName", "cancelled"); b.Property("DocumentId") .HasColumnType("integer") - .HasColumnName("docid"); + .HasColumnName("docid") + .HasAnnotation("Mongo:ElementName", "docid"); b.Property("DocumentName") .HasMaxLength(250) .HasColumnType("character varying(250)") - .HasColumnName("docname"); + .HasColumnName("docname") + .HasAnnotation("Mongo:ElementName", "docname"); b.Property("DocumentPath") .HasMaxLength(1024) .HasColumnType("character varying(1024)") - .HasColumnName("docpath"); + .HasColumnName("docpath") + .HasAnnotation("Mongo:ElementName", "docpath"); b.Property("DocumentTemplate") .HasMaxLength(100) .HasColumnType("character varying(100)") - .HasColumnName("doctemplate"); + .HasColumnName("doctemplate") + .HasAnnotation("Mongo:ElementName", "doctemplate"); b.Property("DocumentType") .HasMaxLength(100) .HasColumnType("character varying(100)") - .HasColumnName("doctype"); + .HasColumnName("doctype") + .HasAnnotation("Mongo:ElementName", "doctype"); b.Property("EventArgs") .HasMaxLength(8000) .HasColumnType("character varying(8000)") - .HasColumnName("args"); + .HasColumnName("args") + .HasAnnotation("Mongo:ElementName", "args"); b.Property("EventType") .IsRequired() .HasMaxLength(100) .HasColumnType("character varying(100)") - .HasColumnName("type"); + .HasColumnName("type") + .HasAnnotation("Mongo:ElementName", "type"); b.Property("HandlerId") .HasColumnType("uuid") - .HasColumnName("handler_id"); + .HasColumnName("handler_id") + .HasAnnotation("Mongo:ElementName", "handler_id"); b.Property("HostUsername") .HasMaxLength(100) .HasColumnType("character varying(100)") - .HasColumnName("host_user"); + .HasColumnName("host_user") + .HasAnnotation("Mongo:ElementName", "host_user"); b.Property("Meta") .IsRequired() .HasColumnType("text") - .HasColumnName("meta"); + .HasColumnName("meta") + .HasAnnotation("Mongo:ElementName", "meta"); b.Property("ProjectName") .HasMaxLength(250) .HasColumnType("character varying(250)") - .HasColumnName("projectname"); + .HasColumnName("projectname") + .HasAnnotation("Mongo:ElementName", "projectname"); b.Property("ProjectNum") .HasMaxLength(100) .HasColumnType("character varying(100)") - .HasColumnName("projectnum"); + .HasColumnName("projectnum") + .HasAnnotation("Mongo:ElementName", "projectnum"); b.Property("RevitBuild") .IsRequired() .HasMaxLength(100) .HasColumnType("character varying(100)") - .HasColumnName("revitbuild"); + .HasColumnName("revitbuild") + .HasAnnotation("Mongo:ElementName", "revitbuild"); b.Property("RevitVersion") .IsRequired() .HasMaxLength(100) .HasColumnType("character varying(100)") - .HasColumnName("revit"); + .HasColumnName("revit") + .HasAnnotation("Mongo:ElementName", "revit"); b.Property("Status") .HasMaxLength(100) .HasColumnType("character varying(100)") - .HasColumnName("status"); + .HasColumnName("status") + .HasAnnotation("Mongo:ElementName", "status"); b.Property("Timestamp") .HasColumnType("timestamp with time zone") - .HasColumnName("timestamp"); + .HasColumnName("timestamp") + .HasAnnotation("Mongo:ElementName", "timestamp"); b.Property("Username") .IsRequired() .HasMaxLength(100) .HasColumnType("character varying(100)") - .HasColumnName("username"); + .HasColumnName("username") + .HasAnnotation("Mongo:ElementName", "username"); b.HasKey("Id"); - b.ToTable("event_record", (string)null); + b.ToTable("events", (string)null); + + b.HasAnnotation("Mongo:CollectionName", "events"); }); modelBuilder.Entity("Telemetry.Api.Domain.Models.ScriptRecord", b => @@ -133,135 +155,162 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("uuid") - .HasColumnName("id"); + .HasColumnName("_id") + .HasAnnotation("Mongo:ElementName", "_id"); b.Property("CloneName") .IsRequired() .HasMaxLength(100) .HasColumnType("character varying(100)") - .HasColumnName("clone"); + .HasColumnName("clone") + .HasAnnotation("Mongo:ElementName", "clone"); b.Property("CommandBundle") .IsRequired() .HasMaxLength(250) .HasColumnType("character varying(250)") - .HasColumnName("commandbundle"); + .HasColumnName("commandbundle") + .HasAnnotation("Mongo:ElementName", "commandbundle"); b.Property("CommandExtension") .IsRequired() .HasMaxLength(250) .HasColumnType("character varying(250)") - .HasColumnName("commandextension"); + .HasColumnName("commandextension") + .HasAnnotation("Mongo:ElementName", "commandextension"); b.Property("CommandName") .IsRequired() .HasMaxLength(250) .HasColumnType("character varying(250)") - .HasColumnName("commandname"); + .HasColumnName("commandname") + .HasAnnotation("Mongo:ElementName", "commandname"); b.Property("CommandResults") .HasMaxLength(8000) .HasColumnType("character varying(8000)") - .HasColumnName("commandresults"); + .HasColumnName("commandresults") + .HasAnnotation("Mongo:ElementName", "commandresults"); b.Property("CommandUniqueName") .IsRequired() .HasMaxLength(500) .HasColumnType("character varying(500)") - .HasColumnName("commanduniquename"); + .HasColumnName("commanduniquename") + .HasAnnotation("Mongo:ElementName", "commanduniquename"); b.Property("DocumentName") .HasMaxLength(250) .HasColumnType("character varying(250)") - .HasColumnName("docname"); + .HasColumnName("docname") + .HasAnnotation("Mongo:ElementName", "docname"); b.Property("DocumentPath") .HasMaxLength(1024) .HasColumnType("character varying(1024)") - .HasColumnName("docpath"); + .HasColumnName("docpath") + .HasAnnotation("Mongo:ElementName", "docpath"); b.Property("ExecId") .IsRequired() .HasMaxLength(100) .HasColumnType("character varying(100)") - .HasColumnName("exec_id"); + .HasColumnName("exec_id") + .HasAnnotation("Mongo:ElementName", "exec_id"); b.Property("ExecTimestamp") .HasColumnType("timestamp with time zone") - .HasColumnName("exec_timestamp"); + .HasColumnName("exec_timestamp") + .HasAnnotation("Mongo:ElementName", "exec_timestamp"); b.Property("HostUsername") .HasMaxLength(100) .HasColumnType("character varying(100)") - .HasColumnName("host_user"); + .HasColumnName("host_user") + .HasAnnotation("Mongo:ElementName", "host_user"); b.Property("IsConfig") .HasColumnType("boolean") - .HasColumnName("config"); + .HasColumnName("config") + .HasAnnotation("Mongo:ElementName", "config"); b.Property("IsDebug") .HasColumnType("boolean") - .HasColumnName("debug"); + .HasColumnName("debug") + .HasAnnotation("Mongo:ElementName", "debug"); b.Property("IsExecFromGui") .HasColumnType("boolean") - .HasColumnName("from_gui"); + .HasColumnName("from_gui") + .HasAnnotation("Mongo:ElementName", "from_gui"); b.Property("Meta") .IsRequired() .HasColumnType("text") - .HasColumnName("meta"); + .HasColumnName("meta") + .HasAnnotation("Mongo:ElementName", "meta"); b.Property("PyRevitVersion") .IsRequired() .HasMaxLength(100) .HasColumnType("character varying(100)") - .HasColumnName("pyrevit"); + .HasColumnName("pyrevit") + .HasAnnotation("Mongo:ElementName", "pyrevit"); b.Property("ResultCode") .HasColumnType("integer") - .HasColumnName("resultcode"); + .HasColumnName("resultcode") + .HasAnnotation("Mongo:ElementName", "resultcode"); b.Property("RevitBuild") .IsRequired() .HasMaxLength(100) .HasColumnType("character varying(100)") - .HasColumnName("revitbuild"); + .HasColumnName("revitbuild") + .HasAnnotation("Mongo:ElementName", "revitbuild"); b.Property("RevitVersion") .IsRequired() .HasMaxLength(100) .HasColumnType("character varying(100)") - .HasColumnName("revit"); + .HasColumnName("revit") + .HasAnnotation("Mongo:ElementName", "revit"); b.Property("ScriptPath") .IsRequired() .HasMaxLength(1024) .HasColumnType("character varying(1024)") - .HasColumnName("scriptpath"); + .HasColumnName("scriptpath") + .HasAnnotation("Mongo:ElementName", "scriptpath"); b.Property("SessionId") .HasColumnType("uuid") - .HasColumnName("sessionid"); + .HasColumnName("sessionid") + .HasAnnotation("Mongo:ElementName", "sessionid"); b.Property("Timestamp") .HasColumnType("timestamp with time zone") - .HasColumnName("timestamp"); + .HasColumnName("timestamp") + .HasAnnotation("Mongo:ElementName", "timestamp"); b.Property("Trace") .IsRequired() .HasColumnType("text") - .HasColumnName("trace"); + .HasColumnName("trace") + .HasAnnotation("Mongo:ElementName", "trace"); b.Property("Username") .IsRequired() .HasMaxLength(100) .HasColumnType("character varying(100)") - .HasColumnName("username"); + .HasColumnName("username") + .HasAnnotation("Mongo:ElementName", "username"); b.HasKey("Id"); - b.ToTable("script_record", (string)null); + b.ToTable("scripts", (string)null); + + b.HasAnnotation("Mongo:CollectionName", "scripts"); }); #pragma warning restore 612, 618 } diff --git a/src/Telemetry.Migrations.SqlServer/Migrations/20260406102100_UpdateDynamicDataSqlServer.Designer.cs b/src/Telemetry.Migrations.SqlServer/Migrations/20260406102100_UpdateDynamicDataSqlServer.Designer.cs new file mode 100644 index 0000000..3d60a45 --- /dev/null +++ b/src/Telemetry.Migrations.SqlServer/Migrations/20260406102100_UpdateDynamicDataSqlServer.Designer.cs @@ -0,0 +1,321 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Telemetry.Api.Infrastructure.Persistence; + +#nullable disable + +namespace Telemetry.Migrations.SqlServer.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20260406102100_UpdateDynamicDataSqlServer")] + partial class UpdateDynamicDataSqlServer + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "10.0.5") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Telemetry.Api.Domain.Models.EventRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnName("_id") + .HasAnnotation("Mongo:ElementName", "_id"); + + b.Property("Cancellable") + .HasColumnType("bit") + .HasColumnName("cancellable") + .HasAnnotation("Mongo:ElementName", "cancellable"); + + b.Property("Cancelled") + .HasColumnType("bit") + .HasColumnName("cancelled") + .HasAnnotation("Mongo:ElementName", "cancelled"); + + b.Property("DocumentId") + .HasColumnType("int") + .HasColumnName("docid") + .HasAnnotation("Mongo:ElementName", "docid"); + + b.Property("DocumentName") + .HasMaxLength(250) + .HasColumnType("nvarchar(250)") + .HasColumnName("docname") + .HasAnnotation("Mongo:ElementName", "docname"); + + b.Property("DocumentPath") + .HasMaxLength(1024) + .HasColumnType("nvarchar(1024)") + .HasColumnName("docpath") + .HasAnnotation("Mongo:ElementName", "docpath"); + + b.Property("DocumentTemplate") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("doctemplate") + .HasAnnotation("Mongo:ElementName", "doctemplate"); + + b.Property("DocumentType") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("doctype") + .HasAnnotation("Mongo:ElementName", "doctype"); + + b.Property("EventArgs") + .HasMaxLength(8000) + .HasColumnType("nvarchar(max)") + .HasColumnName("args") + .HasAnnotation("Mongo:ElementName", "args"); + + b.Property("EventType") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("type") + .HasAnnotation("Mongo:ElementName", "type"); + + b.Property("HandlerId") + .HasColumnType("uniqueidentifier") + .HasColumnName("handler_id") + .HasAnnotation("Mongo:ElementName", "handler_id"); + + b.Property("HostUsername") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("host_user") + .HasAnnotation("Mongo:ElementName", "host_user"); + + b.Property("Meta") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("meta") + .HasAnnotation("Mongo:ElementName", "meta"); + + b.Property("ProjectName") + .HasMaxLength(250) + .HasColumnType("nvarchar(250)") + .HasColumnName("projectname") + .HasAnnotation("Mongo:ElementName", "projectname"); + + b.Property("ProjectNum") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("projectnum") + .HasAnnotation("Mongo:ElementName", "projectnum"); + + b.Property("RevitBuild") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("revitbuild") + .HasAnnotation("Mongo:ElementName", "revitbuild"); + + b.Property("RevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("revit") + .HasAnnotation("Mongo:ElementName", "revit"); + + b.Property("Status") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("status") + .HasAnnotation("Mongo:ElementName", "status"); + + b.Property("Timestamp") + .HasColumnType("datetimeoffset") + .HasColumnName("timestamp") + .HasAnnotation("Mongo:ElementName", "timestamp"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("username") + .HasAnnotation("Mongo:ElementName", "username"); + + b.HasKey("Id"); + + b.ToTable("events", (string)null); + + b.HasAnnotation("Mongo:CollectionName", "events"); + }); + + modelBuilder.Entity("Telemetry.Api.Domain.Models.ScriptRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnName("_id") + .HasAnnotation("Mongo:ElementName", "_id"); + + b.Property("CloneName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("clone") + .HasAnnotation("Mongo:ElementName", "clone"); + + b.Property("CommandBundle") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("nvarchar(250)") + .HasColumnName("commandbundle") + .HasAnnotation("Mongo:ElementName", "commandbundle"); + + b.Property("CommandExtension") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("nvarchar(250)") + .HasColumnName("commandextension") + .HasAnnotation("Mongo:ElementName", "commandextension"); + + b.Property("CommandName") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("nvarchar(250)") + .HasColumnName("commandname") + .HasAnnotation("Mongo:ElementName", "commandname"); + + b.Property("CommandResults") + .HasMaxLength(8000) + .HasColumnType("nvarchar(max)") + .HasColumnName("commandresults") + .HasAnnotation("Mongo:ElementName", "commandresults"); + + b.Property("CommandUniqueName") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("nvarchar(500)") + .HasColumnName("commanduniquename") + .HasAnnotation("Mongo:ElementName", "commanduniquename"); + + b.Property("DocumentName") + .HasMaxLength(250) + .HasColumnType("nvarchar(250)") + .HasColumnName("docname") + .HasAnnotation("Mongo:ElementName", "docname"); + + b.Property("DocumentPath") + .HasMaxLength(1024) + .HasColumnType("nvarchar(1024)") + .HasColumnName("docpath") + .HasAnnotation("Mongo:ElementName", "docpath"); + + b.Property("ExecId") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("exec_id") + .HasAnnotation("Mongo:ElementName", "exec_id"); + + b.Property("ExecTimestamp") + .HasColumnType("datetimeoffset") + .HasColumnName("exec_timestamp") + .HasAnnotation("Mongo:ElementName", "exec_timestamp"); + + b.Property("HostUsername") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("host_user") + .HasAnnotation("Mongo:ElementName", "host_user"); + + b.Property("IsConfig") + .HasColumnType("bit") + .HasColumnName("config") + .HasAnnotation("Mongo:ElementName", "config"); + + b.Property("IsDebug") + .HasColumnType("bit") + .HasColumnName("debug") + .HasAnnotation("Mongo:ElementName", "debug"); + + b.Property("IsExecFromGui") + .HasColumnType("bit") + .HasColumnName("from_gui") + .HasAnnotation("Mongo:ElementName", "from_gui"); + + b.Property("Meta") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("meta") + .HasAnnotation("Mongo:ElementName", "meta"); + + b.Property("PyRevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("pyrevit") + .HasAnnotation("Mongo:ElementName", "pyrevit"); + + b.Property("ResultCode") + .HasColumnType("int") + .HasColumnName("resultcode") + .HasAnnotation("Mongo:ElementName", "resultcode"); + + b.Property("RevitBuild") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("revitbuild") + .HasAnnotation("Mongo:ElementName", "revitbuild"); + + b.Property("RevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("revit") + .HasAnnotation("Mongo:ElementName", "revit"); + + b.Property("ScriptPath") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("nvarchar(1024)") + .HasColumnName("scriptpath") + .HasAnnotation("Mongo:ElementName", "scriptpath"); + + b.Property("SessionId") + .HasColumnType("uniqueidentifier") + .HasColumnName("sessionid") + .HasAnnotation("Mongo:ElementName", "sessionid"); + + b.Property("Timestamp") + .HasColumnType("datetimeoffset") + .HasColumnName("timestamp") + .HasAnnotation("Mongo:ElementName", "timestamp"); + + b.Property("Trace") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("trace") + .HasAnnotation("Mongo:ElementName", "trace"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("username") + .HasAnnotation("Mongo:ElementName", "username"); + + b.HasKey("Id"); + + b.ToTable("scripts", (string)null); + + b.HasAnnotation("Mongo:CollectionName", "scripts"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Telemetry.Migrations.SqlServer/Migrations/20260406102100_UpdateDynamicDataSqlServer.cs b/src/Telemetry.Migrations.SqlServer/Migrations/20260406102100_UpdateDynamicDataSqlServer.cs new file mode 100644 index 0000000..b940889 --- /dev/null +++ b/src/Telemetry.Migrations.SqlServer/Migrations/20260406102100_UpdateDynamicDataSqlServer.cs @@ -0,0 +1,90 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Telemetry.Migrations.SqlServer.Migrations +{ + /// + public partial class UpdateDynamicDataSqlServer : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropPrimaryKey( + name: "PK_script_record", + table: "script_record"); + + migrationBuilder.DropPrimaryKey( + name: "PK_event_record", + table: "event_record"); + + migrationBuilder.RenameTable( + name: "script_record", + newName: "scripts"); + + migrationBuilder.RenameTable( + name: "event_record", + newName: "events"); + + migrationBuilder.RenameColumn( + name: "id", + table: "scripts", + newName: "_id"); + + migrationBuilder.RenameColumn( + name: "id", + table: "events", + newName: "_id"); + + migrationBuilder.AddPrimaryKey( + name: "PK_scripts", + table: "scripts", + column: "_id"); + + migrationBuilder.AddPrimaryKey( + name: "PK_events", + table: "events", + column: "_id"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropPrimaryKey( + name: "PK_scripts", + table: "scripts"); + + migrationBuilder.DropPrimaryKey( + name: "PK_events", + table: "events"); + + migrationBuilder.RenameTable( + name: "scripts", + newName: "script_record"); + + migrationBuilder.RenameTable( + name: "events", + newName: "event_record"); + + migrationBuilder.RenameColumn( + name: "_id", + table: "script_record", + newName: "id"); + + migrationBuilder.RenameColumn( + name: "_id", + table: "event_record", + newName: "id"); + + migrationBuilder.AddPrimaryKey( + name: "PK_script_record", + table: "script_record", + column: "id"); + + migrationBuilder.AddPrimaryKey( + name: "PK_event_record", + table: "event_record", + column: "id"); + } + } +} diff --git a/src/Telemetry.Migrations.SqlServer/Migrations/ApplicationDbContextModelSnapshot.cs b/src/Telemetry.Migrations.SqlServer/Migrations/ApplicationDbContextModelSnapshot.cs index e43d7b4..0a97dea 100644 --- a/src/Telemetry.Migrations.SqlServer/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/src/Telemetry.Migrations.SqlServer/Migrations/ApplicationDbContextModelSnapshot.cs @@ -27,105 +27,127 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("uniqueidentifier") - .HasColumnName("id"); + .HasColumnName("_id") + .HasAnnotation("Mongo:ElementName", "_id"); b.Property("Cancellable") .HasColumnType("bit") - .HasColumnName("cancellable"); + .HasColumnName("cancellable") + .HasAnnotation("Mongo:ElementName", "cancellable"); b.Property("Cancelled") .HasColumnType("bit") - .HasColumnName("cancelled"); + .HasColumnName("cancelled") + .HasAnnotation("Mongo:ElementName", "cancelled"); b.Property("DocumentId") .HasColumnType("int") - .HasColumnName("docid"); + .HasColumnName("docid") + .HasAnnotation("Mongo:ElementName", "docid"); b.Property("DocumentName") .HasMaxLength(250) .HasColumnType("nvarchar(250)") - .HasColumnName("docname"); + .HasColumnName("docname") + .HasAnnotation("Mongo:ElementName", "docname"); b.Property("DocumentPath") .HasMaxLength(1024) .HasColumnType("nvarchar(1024)") - .HasColumnName("docpath"); + .HasColumnName("docpath") + .HasAnnotation("Mongo:ElementName", "docpath"); b.Property("DocumentTemplate") .HasMaxLength(100) .HasColumnType("nvarchar(100)") - .HasColumnName("doctemplate"); + .HasColumnName("doctemplate") + .HasAnnotation("Mongo:ElementName", "doctemplate"); b.Property("DocumentType") .HasMaxLength(100) .HasColumnType("nvarchar(100)") - .HasColumnName("doctype"); + .HasColumnName("doctype") + .HasAnnotation("Mongo:ElementName", "doctype"); b.Property("EventArgs") .HasMaxLength(8000) .HasColumnType("nvarchar(max)") - .HasColumnName("args"); + .HasColumnName("args") + .HasAnnotation("Mongo:ElementName", "args"); b.Property("EventType") .IsRequired() .HasMaxLength(100) .HasColumnType("nvarchar(100)") - .HasColumnName("type"); + .HasColumnName("type") + .HasAnnotation("Mongo:ElementName", "type"); b.Property("HandlerId") .HasColumnType("uniqueidentifier") - .HasColumnName("handler_id"); + .HasColumnName("handler_id") + .HasAnnotation("Mongo:ElementName", "handler_id"); b.Property("HostUsername") .HasMaxLength(100) .HasColumnType("nvarchar(100)") - .HasColumnName("host_user"); + .HasColumnName("host_user") + .HasAnnotation("Mongo:ElementName", "host_user"); b.Property("Meta") .IsRequired() .HasColumnType("nvarchar(max)") - .HasColumnName("meta"); + .HasColumnName("meta") + .HasAnnotation("Mongo:ElementName", "meta"); b.Property("ProjectName") .HasMaxLength(250) .HasColumnType("nvarchar(250)") - .HasColumnName("projectname"); + .HasColumnName("projectname") + .HasAnnotation("Mongo:ElementName", "projectname"); b.Property("ProjectNum") .HasMaxLength(100) .HasColumnType("nvarchar(100)") - .HasColumnName("projectnum"); + .HasColumnName("projectnum") + .HasAnnotation("Mongo:ElementName", "projectnum"); b.Property("RevitBuild") .IsRequired() .HasMaxLength(100) .HasColumnType("nvarchar(100)") - .HasColumnName("revitbuild"); + .HasColumnName("revitbuild") + .HasAnnotation("Mongo:ElementName", "revitbuild"); b.Property("RevitVersion") .IsRequired() .HasMaxLength(100) .HasColumnType("nvarchar(100)") - .HasColumnName("revit"); + .HasColumnName("revit") + .HasAnnotation("Mongo:ElementName", "revit"); b.Property("Status") .HasMaxLength(100) .HasColumnType("nvarchar(100)") - .HasColumnName("status"); + .HasColumnName("status") + .HasAnnotation("Mongo:ElementName", "status"); b.Property("Timestamp") .HasColumnType("datetimeoffset") - .HasColumnName("timestamp"); + .HasColumnName("timestamp") + .HasAnnotation("Mongo:ElementName", "timestamp"); b.Property("Username") .IsRequired() .HasMaxLength(100) .HasColumnType("nvarchar(100)") - .HasColumnName("username"); + .HasColumnName("username") + .HasAnnotation("Mongo:ElementName", "username"); b.HasKey("Id"); - b.ToTable("event_record", (string)null); + b.ToTable("events", (string)null); + + b.HasAnnotation("Mongo:CollectionName", "events"); }); modelBuilder.Entity("Telemetry.Api.Domain.Models.ScriptRecord", b => @@ -133,135 +155,162 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("uniqueidentifier") - .HasColumnName("id"); + .HasColumnName("_id") + .HasAnnotation("Mongo:ElementName", "_id"); b.Property("CloneName") .IsRequired() .HasMaxLength(100) .HasColumnType("nvarchar(100)") - .HasColumnName("clone"); + .HasColumnName("clone") + .HasAnnotation("Mongo:ElementName", "clone"); b.Property("CommandBundle") .IsRequired() .HasMaxLength(250) .HasColumnType("nvarchar(250)") - .HasColumnName("commandbundle"); + .HasColumnName("commandbundle") + .HasAnnotation("Mongo:ElementName", "commandbundle"); b.Property("CommandExtension") .IsRequired() .HasMaxLength(250) .HasColumnType("nvarchar(250)") - .HasColumnName("commandextension"); + .HasColumnName("commandextension") + .HasAnnotation("Mongo:ElementName", "commandextension"); b.Property("CommandName") .IsRequired() .HasMaxLength(250) .HasColumnType("nvarchar(250)") - .HasColumnName("commandname"); + .HasColumnName("commandname") + .HasAnnotation("Mongo:ElementName", "commandname"); b.Property("CommandResults") .HasMaxLength(8000) .HasColumnType("nvarchar(max)") - .HasColumnName("commandresults"); + .HasColumnName("commandresults") + .HasAnnotation("Mongo:ElementName", "commandresults"); b.Property("CommandUniqueName") .IsRequired() .HasMaxLength(500) .HasColumnType("nvarchar(500)") - .HasColumnName("commanduniquename"); + .HasColumnName("commanduniquename") + .HasAnnotation("Mongo:ElementName", "commanduniquename"); b.Property("DocumentName") .HasMaxLength(250) .HasColumnType("nvarchar(250)") - .HasColumnName("docname"); + .HasColumnName("docname") + .HasAnnotation("Mongo:ElementName", "docname"); b.Property("DocumentPath") .HasMaxLength(1024) .HasColumnType("nvarchar(1024)") - .HasColumnName("docpath"); + .HasColumnName("docpath") + .HasAnnotation("Mongo:ElementName", "docpath"); b.Property("ExecId") .IsRequired() .HasMaxLength(100) .HasColumnType("nvarchar(100)") - .HasColumnName("exec_id"); + .HasColumnName("exec_id") + .HasAnnotation("Mongo:ElementName", "exec_id"); b.Property("ExecTimestamp") .HasColumnType("datetimeoffset") - .HasColumnName("exec_timestamp"); + .HasColumnName("exec_timestamp") + .HasAnnotation("Mongo:ElementName", "exec_timestamp"); b.Property("HostUsername") .HasMaxLength(100) .HasColumnType("nvarchar(100)") - .HasColumnName("host_user"); + .HasColumnName("host_user") + .HasAnnotation("Mongo:ElementName", "host_user"); b.Property("IsConfig") .HasColumnType("bit") - .HasColumnName("config"); + .HasColumnName("config") + .HasAnnotation("Mongo:ElementName", "config"); b.Property("IsDebug") .HasColumnType("bit") - .HasColumnName("debug"); + .HasColumnName("debug") + .HasAnnotation("Mongo:ElementName", "debug"); b.Property("IsExecFromGui") .HasColumnType("bit") - .HasColumnName("from_gui"); + .HasColumnName("from_gui") + .HasAnnotation("Mongo:ElementName", "from_gui"); b.Property("Meta") .IsRequired() .HasColumnType("nvarchar(max)") - .HasColumnName("meta"); + .HasColumnName("meta") + .HasAnnotation("Mongo:ElementName", "meta"); b.Property("PyRevitVersion") .IsRequired() .HasMaxLength(100) .HasColumnType("nvarchar(100)") - .HasColumnName("pyrevit"); + .HasColumnName("pyrevit") + .HasAnnotation("Mongo:ElementName", "pyrevit"); b.Property("ResultCode") .HasColumnType("int") - .HasColumnName("resultcode"); + .HasColumnName("resultcode") + .HasAnnotation("Mongo:ElementName", "resultcode"); b.Property("RevitBuild") .IsRequired() .HasMaxLength(100) .HasColumnType("nvarchar(100)") - .HasColumnName("revitbuild"); + .HasColumnName("revitbuild") + .HasAnnotation("Mongo:ElementName", "revitbuild"); b.Property("RevitVersion") .IsRequired() .HasMaxLength(100) .HasColumnType("nvarchar(100)") - .HasColumnName("revit"); + .HasColumnName("revit") + .HasAnnotation("Mongo:ElementName", "revit"); b.Property("ScriptPath") .IsRequired() .HasMaxLength(1024) .HasColumnType("nvarchar(1024)") - .HasColumnName("scriptpath"); + .HasColumnName("scriptpath") + .HasAnnotation("Mongo:ElementName", "scriptpath"); b.Property("SessionId") .HasColumnType("uniqueidentifier") - .HasColumnName("sessionid"); + .HasColumnName("sessionid") + .HasAnnotation("Mongo:ElementName", "sessionid"); b.Property("Timestamp") .HasColumnType("datetimeoffset") - .HasColumnName("timestamp"); + .HasColumnName("timestamp") + .HasAnnotation("Mongo:ElementName", "timestamp"); b.Property("Trace") .IsRequired() .HasColumnType("nvarchar(max)") - .HasColumnName("trace"); + .HasColumnName("trace") + .HasAnnotation("Mongo:ElementName", "trace"); b.Property("Username") .IsRequired() .HasMaxLength(100) .HasColumnType("nvarchar(100)") - .HasColumnName("username"); + .HasColumnName("username") + .HasAnnotation("Mongo:ElementName", "username"); b.HasKey("Id"); - b.ToTable("script_record", (string)null); + b.ToTable("scripts", (string)null); + + b.HasAnnotation("Mongo:CollectionName", "scripts"); }); #pragma warning restore 612, 618 } diff --git a/src/Telemetry.Migrations.Sqlite/Migrations/20260406102040_UpdateDynamicDataSqlite.Designer.cs b/src/Telemetry.Migrations.Sqlite/Migrations/20260406102040_UpdateDynamicDataSqlite.Designer.cs new file mode 100644 index 0000000..0397734 --- /dev/null +++ b/src/Telemetry.Migrations.Sqlite/Migrations/20260406102040_UpdateDynamicDataSqlite.Designer.cs @@ -0,0 +1,316 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Telemetry.Api.Infrastructure.Persistence; + +#nullable disable + +namespace Telemetry.Migrations.Sqlite.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20260406102040_UpdateDynamicDataSqlite")] + partial class UpdateDynamicDataSqlite + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "10.0.5"); + + modelBuilder.Entity("Telemetry.Api.Domain.Models.EventRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT") + .HasColumnName("_id") + .HasAnnotation("Mongo:ElementName", "_id"); + + b.Property("Cancellable") + .HasColumnType("INTEGER") + .HasColumnName("cancellable") + .HasAnnotation("Mongo:ElementName", "cancellable"); + + b.Property("Cancelled") + .HasColumnType("INTEGER") + .HasColumnName("cancelled") + .HasAnnotation("Mongo:ElementName", "cancelled"); + + b.Property("DocumentId") + .HasColumnType("INTEGER") + .HasColumnName("docid") + .HasAnnotation("Mongo:ElementName", "docid"); + + b.Property("DocumentName") + .HasMaxLength(250) + .HasColumnType("TEXT") + .HasColumnName("docname") + .HasAnnotation("Mongo:ElementName", "docname"); + + b.Property("DocumentPath") + .HasMaxLength(1024) + .HasColumnType("TEXT") + .HasColumnName("docpath") + .HasAnnotation("Mongo:ElementName", "docpath"); + + b.Property("DocumentTemplate") + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("doctemplate") + .HasAnnotation("Mongo:ElementName", "doctemplate"); + + b.Property("DocumentType") + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("doctype") + .HasAnnotation("Mongo:ElementName", "doctype"); + + b.Property("EventArgs") + .HasMaxLength(8000) + .HasColumnType("TEXT") + .HasColumnName("args") + .HasAnnotation("Mongo:ElementName", "args"); + + b.Property("EventType") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("type") + .HasAnnotation("Mongo:ElementName", "type"); + + b.Property("HandlerId") + .HasColumnType("TEXT") + .HasColumnName("handler_id") + .HasAnnotation("Mongo:ElementName", "handler_id"); + + b.Property("HostUsername") + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("host_user") + .HasAnnotation("Mongo:ElementName", "host_user"); + + b.Property("Meta") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("meta") + .HasAnnotation("Mongo:ElementName", "meta"); + + b.Property("ProjectName") + .HasMaxLength(250) + .HasColumnType("TEXT") + .HasColumnName("projectname") + .HasAnnotation("Mongo:ElementName", "projectname"); + + b.Property("ProjectNum") + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("projectnum") + .HasAnnotation("Mongo:ElementName", "projectnum"); + + b.Property("RevitBuild") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("revitbuild") + .HasAnnotation("Mongo:ElementName", "revitbuild"); + + b.Property("RevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("revit") + .HasAnnotation("Mongo:ElementName", "revit"); + + b.Property("Status") + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("status") + .HasAnnotation("Mongo:ElementName", "status"); + + b.Property("Timestamp") + .HasColumnType("TEXT") + .HasColumnName("timestamp") + .HasAnnotation("Mongo:ElementName", "timestamp"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("username") + .HasAnnotation("Mongo:ElementName", "username"); + + b.HasKey("Id"); + + b.ToTable("events", (string)null); + + b.HasAnnotation("Mongo:CollectionName", "events"); + }); + + modelBuilder.Entity("Telemetry.Api.Domain.Models.ScriptRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT") + .HasColumnName("_id") + .HasAnnotation("Mongo:ElementName", "_id"); + + b.Property("CloneName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("clone") + .HasAnnotation("Mongo:ElementName", "clone"); + + b.Property("CommandBundle") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("TEXT") + .HasColumnName("commandbundle") + .HasAnnotation("Mongo:ElementName", "commandbundle"); + + b.Property("CommandExtension") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("TEXT") + .HasColumnName("commandextension") + .HasAnnotation("Mongo:ElementName", "commandextension"); + + b.Property("CommandName") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("TEXT") + .HasColumnName("commandname") + .HasAnnotation("Mongo:ElementName", "commandname"); + + b.Property("CommandResults") + .HasMaxLength(8000) + .HasColumnType("TEXT") + .HasColumnName("commandresults") + .HasAnnotation("Mongo:ElementName", "commandresults"); + + b.Property("CommandUniqueName") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("TEXT") + .HasColumnName("commanduniquename") + .HasAnnotation("Mongo:ElementName", "commanduniquename"); + + b.Property("DocumentName") + .HasMaxLength(250) + .HasColumnType("TEXT") + .HasColumnName("docname") + .HasAnnotation("Mongo:ElementName", "docname"); + + b.Property("DocumentPath") + .HasMaxLength(1024) + .HasColumnType("TEXT") + .HasColumnName("docpath") + .HasAnnotation("Mongo:ElementName", "docpath"); + + b.Property("ExecId") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("exec_id") + .HasAnnotation("Mongo:ElementName", "exec_id"); + + b.Property("ExecTimestamp") + .HasColumnType("TEXT") + .HasColumnName("exec_timestamp") + .HasAnnotation("Mongo:ElementName", "exec_timestamp"); + + b.Property("HostUsername") + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("host_user") + .HasAnnotation("Mongo:ElementName", "host_user"); + + b.Property("IsConfig") + .HasColumnType("INTEGER") + .HasColumnName("config") + .HasAnnotation("Mongo:ElementName", "config"); + + b.Property("IsDebug") + .HasColumnType("INTEGER") + .HasColumnName("debug") + .HasAnnotation("Mongo:ElementName", "debug"); + + b.Property("IsExecFromGui") + .HasColumnType("INTEGER") + .HasColumnName("from_gui") + .HasAnnotation("Mongo:ElementName", "from_gui"); + + b.Property("Meta") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("meta") + .HasAnnotation("Mongo:ElementName", "meta"); + + b.Property("PyRevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("pyrevit") + .HasAnnotation("Mongo:ElementName", "pyrevit"); + + b.Property("ResultCode") + .HasColumnType("INTEGER") + .HasColumnName("resultcode") + .HasAnnotation("Mongo:ElementName", "resultcode"); + + b.Property("RevitBuild") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("revitbuild") + .HasAnnotation("Mongo:ElementName", "revitbuild"); + + b.Property("RevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("revit") + .HasAnnotation("Mongo:ElementName", "revit"); + + b.Property("ScriptPath") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("TEXT") + .HasColumnName("scriptpath") + .HasAnnotation("Mongo:ElementName", "scriptpath"); + + b.Property("SessionId") + .HasColumnType("TEXT") + .HasColumnName("sessionid") + .HasAnnotation("Mongo:ElementName", "sessionid"); + + b.Property("Timestamp") + .HasColumnType("TEXT") + .HasColumnName("timestamp") + .HasAnnotation("Mongo:ElementName", "timestamp"); + + b.Property("Trace") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("trace") + .HasAnnotation("Mongo:ElementName", "trace"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("username") + .HasAnnotation("Mongo:ElementName", "username"); + + b.HasKey("Id"); + + b.ToTable("scripts", (string)null); + + b.HasAnnotation("Mongo:CollectionName", "scripts"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Telemetry.Migrations.Sqlite/Migrations/20260406102040_UpdateDynamicDataSqlite.cs b/src/Telemetry.Migrations.Sqlite/Migrations/20260406102040_UpdateDynamicDataSqlite.cs new file mode 100644 index 0000000..7e0bcb0 --- /dev/null +++ b/src/Telemetry.Migrations.Sqlite/Migrations/20260406102040_UpdateDynamicDataSqlite.cs @@ -0,0 +1,90 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Telemetry.Migrations.Sqlite.Migrations +{ + /// + public partial class UpdateDynamicDataSqlite : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropPrimaryKey( + name: "PK_script_record", + table: "script_record"); + + migrationBuilder.DropPrimaryKey( + name: "PK_event_record", + table: "event_record"); + + migrationBuilder.RenameTable( + name: "script_record", + newName: "scripts"); + + migrationBuilder.RenameTable( + name: "event_record", + newName: "events"); + + migrationBuilder.RenameColumn( + name: "id", + table: "scripts", + newName: "_id"); + + migrationBuilder.RenameColumn( + name: "id", + table: "events", + newName: "_id"); + + migrationBuilder.AddPrimaryKey( + name: "PK_scripts", + table: "scripts", + column: "_id"); + + migrationBuilder.AddPrimaryKey( + name: "PK_events", + table: "events", + column: "_id"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropPrimaryKey( + name: "PK_scripts", + table: "scripts"); + + migrationBuilder.DropPrimaryKey( + name: "PK_events", + table: "events"); + + migrationBuilder.RenameTable( + name: "scripts", + newName: "script_record"); + + migrationBuilder.RenameTable( + name: "events", + newName: "event_record"); + + migrationBuilder.RenameColumn( + name: "_id", + table: "script_record", + newName: "id"); + + migrationBuilder.RenameColumn( + name: "_id", + table: "event_record", + newName: "id"); + + migrationBuilder.AddPrimaryKey( + name: "PK_script_record", + table: "script_record", + column: "id"); + + migrationBuilder.AddPrimaryKey( + name: "PK_event_record", + table: "event_record", + column: "id"); + } + } +} diff --git a/src/Telemetry.Migrations.Sqlite/Migrations/ApplicationDbContextModelSnapshot.cs b/src/Telemetry.Migrations.Sqlite/Migrations/ApplicationDbContextModelSnapshot.cs index 0fc6f6d..e90e216 100644 --- a/src/Telemetry.Migrations.Sqlite/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/src/Telemetry.Migrations.Sqlite/Migrations/ApplicationDbContextModelSnapshot.cs @@ -22,105 +22,127 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("TEXT") - .HasColumnName("id"); + .HasColumnName("_id") + .HasAnnotation("Mongo:ElementName", "_id"); b.Property("Cancellable") .HasColumnType("INTEGER") - .HasColumnName("cancellable"); + .HasColumnName("cancellable") + .HasAnnotation("Mongo:ElementName", "cancellable"); b.Property("Cancelled") .HasColumnType("INTEGER") - .HasColumnName("cancelled"); + .HasColumnName("cancelled") + .HasAnnotation("Mongo:ElementName", "cancelled"); b.Property("DocumentId") .HasColumnType("INTEGER") - .HasColumnName("docid"); + .HasColumnName("docid") + .HasAnnotation("Mongo:ElementName", "docid"); b.Property("DocumentName") .HasMaxLength(250) .HasColumnType("TEXT") - .HasColumnName("docname"); + .HasColumnName("docname") + .HasAnnotation("Mongo:ElementName", "docname"); b.Property("DocumentPath") .HasMaxLength(1024) .HasColumnType("TEXT") - .HasColumnName("docpath"); + .HasColumnName("docpath") + .HasAnnotation("Mongo:ElementName", "docpath"); b.Property("DocumentTemplate") .HasMaxLength(100) .HasColumnType("TEXT") - .HasColumnName("doctemplate"); + .HasColumnName("doctemplate") + .HasAnnotation("Mongo:ElementName", "doctemplate"); b.Property("DocumentType") .HasMaxLength(100) .HasColumnType("TEXT") - .HasColumnName("doctype"); + .HasColumnName("doctype") + .HasAnnotation("Mongo:ElementName", "doctype"); b.Property("EventArgs") .HasMaxLength(8000) .HasColumnType("TEXT") - .HasColumnName("args"); + .HasColumnName("args") + .HasAnnotation("Mongo:ElementName", "args"); b.Property("EventType") .IsRequired() .HasMaxLength(100) .HasColumnType("TEXT") - .HasColumnName("type"); + .HasColumnName("type") + .HasAnnotation("Mongo:ElementName", "type"); b.Property("HandlerId") .HasColumnType("TEXT") - .HasColumnName("handler_id"); + .HasColumnName("handler_id") + .HasAnnotation("Mongo:ElementName", "handler_id"); b.Property("HostUsername") .HasMaxLength(100) .HasColumnType("TEXT") - .HasColumnName("host_user"); + .HasColumnName("host_user") + .HasAnnotation("Mongo:ElementName", "host_user"); b.Property("Meta") .IsRequired() .HasColumnType("TEXT") - .HasColumnName("meta"); + .HasColumnName("meta") + .HasAnnotation("Mongo:ElementName", "meta"); b.Property("ProjectName") .HasMaxLength(250) .HasColumnType("TEXT") - .HasColumnName("projectname"); + .HasColumnName("projectname") + .HasAnnotation("Mongo:ElementName", "projectname"); b.Property("ProjectNum") .HasMaxLength(100) .HasColumnType("TEXT") - .HasColumnName("projectnum"); + .HasColumnName("projectnum") + .HasAnnotation("Mongo:ElementName", "projectnum"); b.Property("RevitBuild") .IsRequired() .HasMaxLength(100) .HasColumnType("TEXT") - .HasColumnName("revitbuild"); + .HasColumnName("revitbuild") + .HasAnnotation("Mongo:ElementName", "revitbuild"); b.Property("RevitVersion") .IsRequired() .HasMaxLength(100) .HasColumnType("TEXT") - .HasColumnName("revit"); + .HasColumnName("revit") + .HasAnnotation("Mongo:ElementName", "revit"); b.Property("Status") .HasMaxLength(100) .HasColumnType("TEXT") - .HasColumnName("status"); + .HasColumnName("status") + .HasAnnotation("Mongo:ElementName", "status"); b.Property("Timestamp") .HasColumnType("TEXT") - .HasColumnName("timestamp"); + .HasColumnName("timestamp") + .HasAnnotation("Mongo:ElementName", "timestamp"); b.Property("Username") .IsRequired() .HasMaxLength(100) .HasColumnType("TEXT") - .HasColumnName("username"); + .HasColumnName("username") + .HasAnnotation("Mongo:ElementName", "username"); b.HasKey("Id"); - b.ToTable("event_record", (string)null); + b.ToTable("events", (string)null); + + b.HasAnnotation("Mongo:CollectionName", "events"); }); modelBuilder.Entity("Telemetry.Api.Domain.Models.ScriptRecord", b => @@ -128,135 +150,162 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("TEXT") - .HasColumnName("id"); + .HasColumnName("_id") + .HasAnnotation("Mongo:ElementName", "_id"); b.Property("CloneName") .IsRequired() .HasMaxLength(100) .HasColumnType("TEXT") - .HasColumnName("clone"); + .HasColumnName("clone") + .HasAnnotation("Mongo:ElementName", "clone"); b.Property("CommandBundle") .IsRequired() .HasMaxLength(250) .HasColumnType("TEXT") - .HasColumnName("commandbundle"); + .HasColumnName("commandbundle") + .HasAnnotation("Mongo:ElementName", "commandbundle"); b.Property("CommandExtension") .IsRequired() .HasMaxLength(250) .HasColumnType("TEXT") - .HasColumnName("commandextension"); + .HasColumnName("commandextension") + .HasAnnotation("Mongo:ElementName", "commandextension"); b.Property("CommandName") .IsRequired() .HasMaxLength(250) .HasColumnType("TEXT") - .HasColumnName("commandname"); + .HasColumnName("commandname") + .HasAnnotation("Mongo:ElementName", "commandname"); b.Property("CommandResults") .HasMaxLength(8000) .HasColumnType("TEXT") - .HasColumnName("commandresults"); + .HasColumnName("commandresults") + .HasAnnotation("Mongo:ElementName", "commandresults"); b.Property("CommandUniqueName") .IsRequired() .HasMaxLength(500) .HasColumnType("TEXT") - .HasColumnName("commanduniquename"); + .HasColumnName("commanduniquename") + .HasAnnotation("Mongo:ElementName", "commanduniquename"); b.Property("DocumentName") .HasMaxLength(250) .HasColumnType("TEXT") - .HasColumnName("docname"); + .HasColumnName("docname") + .HasAnnotation("Mongo:ElementName", "docname"); b.Property("DocumentPath") .HasMaxLength(1024) .HasColumnType("TEXT") - .HasColumnName("docpath"); + .HasColumnName("docpath") + .HasAnnotation("Mongo:ElementName", "docpath"); b.Property("ExecId") .IsRequired() .HasMaxLength(100) .HasColumnType("TEXT") - .HasColumnName("exec_id"); + .HasColumnName("exec_id") + .HasAnnotation("Mongo:ElementName", "exec_id"); b.Property("ExecTimestamp") .HasColumnType("TEXT") - .HasColumnName("exec_timestamp"); + .HasColumnName("exec_timestamp") + .HasAnnotation("Mongo:ElementName", "exec_timestamp"); b.Property("HostUsername") .HasMaxLength(100) .HasColumnType("TEXT") - .HasColumnName("host_user"); + .HasColumnName("host_user") + .HasAnnotation("Mongo:ElementName", "host_user"); b.Property("IsConfig") .HasColumnType("INTEGER") - .HasColumnName("config"); + .HasColumnName("config") + .HasAnnotation("Mongo:ElementName", "config"); b.Property("IsDebug") .HasColumnType("INTEGER") - .HasColumnName("debug"); + .HasColumnName("debug") + .HasAnnotation("Mongo:ElementName", "debug"); b.Property("IsExecFromGui") .HasColumnType("INTEGER") - .HasColumnName("from_gui"); + .HasColumnName("from_gui") + .HasAnnotation("Mongo:ElementName", "from_gui"); b.Property("Meta") .IsRequired() .HasColumnType("TEXT") - .HasColumnName("meta"); + .HasColumnName("meta") + .HasAnnotation("Mongo:ElementName", "meta"); b.Property("PyRevitVersion") .IsRequired() .HasMaxLength(100) .HasColumnType("TEXT") - .HasColumnName("pyrevit"); + .HasColumnName("pyrevit") + .HasAnnotation("Mongo:ElementName", "pyrevit"); b.Property("ResultCode") .HasColumnType("INTEGER") - .HasColumnName("resultcode"); + .HasColumnName("resultcode") + .HasAnnotation("Mongo:ElementName", "resultcode"); b.Property("RevitBuild") .IsRequired() .HasMaxLength(100) .HasColumnType("TEXT") - .HasColumnName("revitbuild"); + .HasColumnName("revitbuild") + .HasAnnotation("Mongo:ElementName", "revitbuild"); b.Property("RevitVersion") .IsRequired() .HasMaxLength(100) .HasColumnType("TEXT") - .HasColumnName("revit"); + .HasColumnName("revit") + .HasAnnotation("Mongo:ElementName", "revit"); b.Property("ScriptPath") .IsRequired() .HasMaxLength(1024) .HasColumnType("TEXT") - .HasColumnName("scriptpath"); + .HasColumnName("scriptpath") + .HasAnnotation("Mongo:ElementName", "scriptpath"); b.Property("SessionId") .HasColumnType("TEXT") - .HasColumnName("sessionid"); + .HasColumnName("sessionid") + .HasAnnotation("Mongo:ElementName", "sessionid"); b.Property("Timestamp") .HasColumnType("TEXT") - .HasColumnName("timestamp"); + .HasColumnName("timestamp") + .HasAnnotation("Mongo:ElementName", "timestamp"); b.Property("Trace") .IsRequired() .HasColumnType("TEXT") - .HasColumnName("trace"); + .HasColumnName("trace") + .HasAnnotation("Mongo:ElementName", "trace"); b.Property("Username") .IsRequired() .HasMaxLength(100) .HasColumnType("TEXT") - .HasColumnName("username"); + .HasColumnName("username") + .HasAnnotation("Mongo:ElementName", "username"); b.HasKey("Id"); - b.ToTable("script_record", (string)null); + b.ToTable("scripts", (string)null); + + b.HasAnnotation("Mongo:CollectionName", "scripts"); }); #pragma warning restore 612, 618 } From e2010957bd57d4e46bb9927f39c6c16d75fbfa75 Mon Sep 17 00:00:00 2001 From: dosymep Date: Mon, 6 Apr 2026 16:24:36 +0600 Subject: [PATCH 19/31] update docker ignore file --- src/Telemetry.Api/.dockerignore | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Telemetry.Api/.dockerignore b/src/Telemetry.Api/.dockerignore index af50df1..4e2bf2a 100644 --- a/src/Telemetry.Api/.dockerignore +++ b/src/Telemetry.Api/.dockerignore @@ -22,4 +22,7 @@ **/secrets.dev.yaml **/values.dev.yaml LICENSE -README.md \ No newline at end of file +README.md + +**/TestResults +**/telemetry-db \ No newline at end of file From 1c430d6238b4200570f3057c75ea34527a2f0701 Mon Sep 17 00:00:00 2001 From: dosymep Date: Mon, 6 Apr 2026 16:24:53 +0600 Subject: [PATCH 20/31] add rider team settings --- telemetry-server.sln.DotSettings | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 telemetry-server.sln.DotSettings diff --git a/telemetry-server.sln.DotSettings b/telemetry-server.sln.DotSettings new file mode 100644 index 0000000..813db91 --- /dev/null +++ b/telemetry-server.sln.DotSettings @@ -0,0 +1,16 @@ + + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True \ No newline at end of file From 59555c67376f2fa137c7ea0a6826f3f1dc42979e Mon Sep 17 00:00:00 2001 From: dosymep Date: Mon, 6 Apr 2026 16:29:47 +0600 Subject: [PATCH 21/31] fix load migration assembly --- src/Telemetry.Api/Program.cs | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/src/Telemetry.Api/Program.cs b/src/Telemetry.Api/Program.cs index 3273f24..83905a4 100644 --- a/src/Telemetry.Api/Program.cs +++ b/src/Telemetry.Api/Program.cs @@ -47,42 +47,35 @@ Log.Information("Using Oracle database"); options.UseOracle(connectionString, x => x.MigrationsAssembly("Telemetry.Migrations.Oracle")); - - Log.Information("Load Oracle migration assembly"); - AssemblyLoadContext.Default.LoadFromAssemblyPath( - Path.Combine(Environment.CurrentDirectory, "Telemetry.Migrations.Oracle.dll")); + + LoadAssembly(dbProvider, "Telemetry.Migrations.Oracle.dll"); break; case "postgres": Log.Information("Using PostgresSQL database"); options.UseNpgsql(connectionString, x => x.MigrationsAssembly("Telemetry.Migrations.Postgres")); - - Log.Information("Load PostgresSQL migration assembly"); - AssemblyLoadContext.Default.LoadFromAssemblyPath( - Path.Combine(Environment.CurrentDirectory, "Telemetry.Migrations.Postgres.dll")); + + LoadAssembly(dbProvider, "Telemetry.Migrations.Postgres.dll"); break; case "sqlite": Log.Information("Using SQLite database"); options.UseSqlite(connectionString, x => x.MigrationsAssembly("Telemetry.Migrations.Sqlite")); - Log.Information("Load SQLite migration assembly"); - AssemblyLoadContext.Default.LoadFromAssemblyPath( - Path.Combine(Environment.CurrentDirectory, "Telemetry.Migrations.Sqlite.dll")); + LoadAssembly(dbProvider, "Telemetry.Migrations.Sqlite.dll"); break; case "mssql": Log.Information("Using MS SQL database"); options.UseSqlServer(connectionString, x => x.MigrationsAssembly("Telemetry.Migrations.SqlServer")); - Log.Information("Load MS SQL migration assembly"); - AssemblyLoadContext.Default.LoadFromAssemblyPath( - Path.Combine(Environment.CurrentDirectory, "Telemetry.Migrations.SqlServer.dll")); + LoadAssembly(dbProvider, "Telemetry.Migrations.SqlServer.dll"); break; case "mongodb": + Log.Information("Using MongoDB database"); string mongoDbName = builder.Configuration.GetValue("MongoDbDatabaseName") ?? "telemetry"; options.UseMongoDB(connectionString, mongoDbName); - Log.Information("Using MongoDB database"); + break; default: throw new NotSupportedException($"Provider {dbProvider} is not supported."); @@ -177,4 +170,17 @@ catch (Exception ex) { app.Logger.LogCritical(ex, "Host terminated unexpectedly"); +} + +return; + +void LoadAssembly(string provider, string assemlyName) +{ + string assemblyPath = Path.Combine(Environment.CurrentDirectory, assemlyName); + if (File.Exists(assemblyPath)) + { + Log.Information( + "Load {Provider} migration assembly {AssemblyPath}", provider, assemblyPath); + AssemblyLoadContext.Default.LoadFromAssemblyPath(assemblyPath); + } } \ No newline at end of file From f9f651d1554f01ce093266fa4d594ea5b91e30b2 Mon Sep 17 00:00:00 2001 From: dosymep Date: Mon, 6 Apr 2026 17:20:38 +0600 Subject: [PATCH 22/31] add check version --- .../Web/Controllers/TelemetryController.cs | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/Telemetry.Api/Web/Controllers/TelemetryController.cs b/src/Telemetry.Api/Web/Controllers/TelemetryController.cs index ccbce6a..85ee306 100644 --- a/src/Telemetry.Api/Web/Controllers/TelemetryController.cs +++ b/src/Telemetry.Api/Web/Controllers/TelemetryController.cs @@ -40,6 +40,7 @@ public TelemetryController(IApplicationDbContext context, ILoggerReturns adding script records task. [HttpPost("scripts")] [ProducesResponseType(200)] + [ProducesResponseType(400)] [ProducesResponseType(500)] [ProducesResponseType(503)] public async Task PostScript([FromBody] ScriptRecordDto dto) @@ -48,6 +49,16 @@ public async Task PostScript([FromBody] ScriptRecordDto dto) { CancellationToken ct = HttpContext.RequestAborted; + if (dto.Meta.SchemaVersion != new Version(2, 0, 0)) + { + return BadRequest(new ProblemDetails() + { + Title = "Unsupported Schema Version", + Detail = $"Expected version 2.0.0, but received {dto.Meta.SchemaVersion}", + Status = StatusCodes.Status400BadRequest + }); + } + ScriptRecord record = dto.ToModel(); _context.ScriptRecords.Add(record); @@ -74,6 +85,7 @@ public async Task PostScript([FromBody] ScriptRecordDto dto) /// Returns adding event records task. [HttpPost("events")] [ProducesResponseType(200)] + [ProducesResponseType(400)] [ProducesResponseType(500)] [ProducesResponseType(503)] public async Task PostEvent([FromBody] EventRecordDto dto) @@ -81,6 +93,16 @@ public async Task PostEvent([FromBody] EventRecordDto dto) try { CancellationToken ct = HttpContext.RequestAborted; + + if (dto.Meta.SchemaVersion != new Version(2, 0, 0)) + { + return BadRequest(new ProblemDetails() + { + Title = "Unsupported Schema Version", + Detail = $"Expected version 2.0.0, but received {dto.Meta.SchemaVersion}", + Status = StatusCodes.Status400BadRequest + }); + } EventRecord record = dto.ToModel(); _context.EventRecords.Add(record); From 56f02dd5f2e887aa494e451ce122089bd1aa3a35 Mon Sep 17 00:00:00 2001 From: dosymep Date: Mon, 6 Apr 2026 17:36:43 +0600 Subject: [PATCH 23/31] sync DB schema with Go service models --- src/Telemetry.Api/Domain/Models/EngineInfo.cs | 6 +-- src/Telemetry.Api/Domain/Models/TraceInfo.cs | 4 +- .../Persistence/ApplicationDbContext.cs | 52 ++++++++++++------- 3 files changed, 34 insertions(+), 28 deletions(-) diff --git a/src/Telemetry.Api/Domain/Models/EngineInfo.cs b/src/Telemetry.Api/Domain/Models/EngineInfo.cs index 5adef1e..31dd97b 100644 --- a/src/Telemetry.Api/Domain/Models/EngineInfo.cs +++ b/src/Telemetry.Api/Domain/Models/EngineInfo.cs @@ -15,28 +15,24 @@ public class EngineInfo ///
Engine types. ///
[MaxLength(100)] - [JsonPropertyName("type")] public required string Type { get; init; } /// /// Engine version. ///
Engines list. ///
- [MaxLength(100)] - [JsonPropertyName("version")] + [MaxLength(100)] public required string Version { get; init; } /// /// System paths using by script. /// - [JsonPropertyName("syspath")] public string[]? SysPaths { get; init; } /// /// Dynamic script configs data. /// [MaxLength(8000)] - [JsonPropertyName("configs")] public string? Configs { get; init; } } } \ No newline at end of file diff --git a/src/Telemetry.Api/Domain/Models/TraceInfo.cs b/src/Telemetry.Api/Domain/Models/TraceInfo.cs index 9541426..6195a52 100644 --- a/src/Telemetry.Api/Domain/Models/TraceInfo.cs +++ b/src/Telemetry.Api/Domain/Models/TraceInfo.cs @@ -13,14 +13,12 @@ public class TraceInfo /// Script executed /// message. ///
- [MaxLength(8000)] - [JsonPropertyName("message")] + [MaxLength(8000)] public required string Message { get; init; } /// /// Script engine information. /// - [JsonPropertyName("engine")] public required EngineInfo Engine { get; init; } } } \ No newline at end of file diff --git a/src/Telemetry.Api/Infrastructure/Persistence/ApplicationDbContext.cs b/src/Telemetry.Api/Infrastructure/Persistence/ApplicationDbContext.cs index dfeae5c..ae85a0e 100644 --- a/src/Telemetry.Api/Infrastructure/Persistence/ApplicationDbContext.cs +++ b/src/Telemetry.Api/Infrastructure/Persistence/ApplicationDbContext.cs @@ -135,6 +135,12 @@ public async Task GetDbVersionAsync(CancellationToken cancellationToken) /// The builder used to define the model structure and relationships. protected override void OnModelCreating(ModelBuilder modelBuilder) { + modelBuilder.Entity() + .Ignore(u => u.Meta); + + modelBuilder.Entity() + .Ignore(u => u.Meta); + modelBuilder.Entity(entity => { entity.ToTable("scripts"); @@ -233,19 +239,32 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) .HasColumnName("commandresults") .HasElementName("commandresults"); - entity.Property(e => e.Meta) - .HasColumnName("meta") - .HasElementName("meta") - .HasConversion( - v => JsonSerializer.Serialize(v, JsonSerializerOptions.Web), - v => JsonSerializer.Deserialize(v, JsonSerializerOptions.Web)!); - - entity.Property(e => e.Trace) - .HasColumnName("trace") - .HasElementName("trace") - .HasConversion( - v => JsonSerializer.Serialize(v, JsonSerializerOptions.Web), - v => JsonSerializer.Deserialize(v, JsonSerializerOptions.Web)!); + entity.OwnsOne(e => e.Trace, trace => + { + trace.Property(e => e.Message) + .HasColumnName("trace_message") + .HasElementName("trace_message"); + + trace.Property(e => e.Engine.Type) + .HasColumnName("engine_type") + .HasElementName("engine_type"); + + trace.Property(e => e.Engine.Version) + .HasColumnName("engine_configs") + .HasElementName("engine_configs"); + + trace.Property(e => e.Engine.Configs) + .HasColumnName("configs") + .HasElementName("configs"); + + trace.Property(e => e.Engine.SysPaths) + .HasColumnName("engine_syspath") + .HasElementName("engine_syspath") + .HasConversion( + v => v == null ? null : string.Join(";", v), + v => string.IsNullOrEmpty(v) ? null : v.Split(";") + ); + }); }); modelBuilder.Entity(entity => @@ -329,13 +348,6 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) entity.Property(e => e.EventArgs) .HasColumnName("args") .HasElementName("args"); - - entity.Property(e => e.Meta) - .HasColumnName("meta") - .HasElementName("meta") - .HasConversion( - v => JsonSerializer.Serialize(v, JsonSerializerOptions.Web), - v => JsonSerializer.Deserialize(v, JsonSerializerOptions.Web)!); }); if (Database.ProviderName!.Equals("MongoDB.EntityFrameworkCore")) From e604bfc25d16129947aaf084c11e7f696f82b488 Mon Sep 17 00:00:00 2001 From: dosymep Date: Mon, 6 Apr 2026 17:45:22 +0600 Subject: [PATCH 24/31] refactor ApplicationDbContext.cs --- .../Mappings/TelemetryMappingExtensions.cs | 6 +- .../Domain/Models/EventRecord.cs | 5 - .../Domain/Models/ScriptRecord.cs | 5 - .../Persistence/ApplicationDbContext.cs | 332 +++++++----------- .../Infrastructure/Persistence/DbConstants.cs | 56 +++ .../TelemetryMappingExtensionsTests.cs | 6 - 6 files changed, 189 insertions(+), 221 deletions(-) create mode 100644 src/Telemetry.Api/Infrastructure/Persistence/DbConstants.cs diff --git a/src/Telemetry.Api/Application/Mappings/TelemetryMappingExtensions.cs b/src/Telemetry.Api/Application/Mappings/TelemetryMappingExtensions.cs index 752f9fe..808d62e 100644 --- a/src/Telemetry.Api/Application/Mappings/TelemetryMappingExtensions.cs +++ b/src/Telemetry.Api/Application/Mappings/TelemetryMappingExtensions.cs @@ -86,7 +86,6 @@ public static ScriptRecord ToModel(this ScriptRecordDto dto) { Id = Guid.CreateVersion7(), SessionId = dto.SessionId, - Meta = dto.Meta.ToModel(), Timestamp = dto.Timestamp, Username = dto.Username, HostUsername = dto.HostUsername, @@ -122,7 +121,7 @@ public static ScriptRecordDto ToDto(this ScriptRecord model) return new ScriptRecordDto { SessionId = model.SessionId, - Meta = model.Meta.ToDto(), + Meta = new MetaDto(){SchemaVersion = new Version(2,0,0)}, Timestamp = model.Timestamp, Username = model.Username, HostUsername = model.HostUsername, @@ -159,7 +158,6 @@ public static EventRecord ToModel(this EventRecordDto dto) { Id = Guid.CreateVersion7(), HandlerId = dto.HandlerId, - Meta = dto.Meta.ToModel(), EventType = dto.EventType, Status = dto.Status, Timestamp = dto.Timestamp, @@ -190,7 +188,7 @@ public static EventRecordDto ToDto(this EventRecord model) return new EventRecordDto { HandlerId = model.HandlerId, - Meta = model.Meta.ToDto(), + Meta = new MetaDto(){SchemaVersion = new Version(2,0,0)}, EventType = model.EventType, Status = model.Status, Timestamp = model.Timestamp, diff --git a/src/Telemetry.Api/Domain/Models/EventRecord.cs b/src/Telemetry.Api/Domain/Models/EventRecord.cs index 9efbabe..2267290 100644 --- a/src/Telemetry.Api/Domain/Models/EventRecord.cs +++ b/src/Telemetry.Api/Domain/Models/EventRecord.cs @@ -19,11 +19,6 @@ public class EventRecord /// Unique event id. /// public Guid HandlerId { get; init; } - - /// - /// Information about telemetry record. - /// - public required MetaRecord Meta { get; init; } /// /// Event type name. diff --git a/src/Telemetry.Api/Domain/Models/ScriptRecord.cs b/src/Telemetry.Api/Domain/Models/ScriptRecord.cs index ef29b27..4f9bde6 100644 --- a/src/Telemetry.Api/Domain/Models/ScriptRecord.cs +++ b/src/Telemetry.Api/Domain/Models/ScriptRecord.cs @@ -22,11 +22,6 @@ public class ScriptRecord /// public Guid SessionId { get; init; } - /// - /// Information about telemetry record. - /// - public required MetaRecord Meta { get; init; } - /// /// When script started. /// diff --git a/src/Telemetry.Api/Infrastructure/Persistence/ApplicationDbContext.cs b/src/Telemetry.Api/Infrastructure/Persistence/ApplicationDbContext.cs index ae85a0e..f08a764 100644 --- a/src/Telemetry.Api/Infrastructure/Persistence/ApplicationDbContext.cs +++ b/src/Telemetry.Api/Infrastructure/Persistence/ApplicationDbContext.cs @@ -135,131 +135,138 @@ public async Task GetDbVersionAsync(CancellationToken cancellationToken) /// The builder used to define the model structure and relationships. protected override void OnModelCreating(ModelBuilder modelBuilder) { - modelBuilder.Entity() - .Ignore(u => u.Meta); + if (Database.ProviderName!.Equals("MongoDB.EntityFrameworkCore")) + { + ConfigureMongoDbModel(modelBuilder); + } + else + { + ConfigureSqlModel(modelBuilder); + } - modelBuilder.Entity() - .Ignore(u => u.Meta); + base.OnModelCreating(modelBuilder); + } + private void ConfigureMongoDbModel(ModelBuilder modelBuilder) + { modelBuilder.Entity(entity => { - entity.ToTable("scripts"); - entity.ToCollection("scripts"); + entity.ToCollection(DbConstants.Tables.Scripts); entity.HasKey(e => e.Id); - entity.Property(e => e.Id) - .HasColumnName("_id") - .HasElementName("_id"); - - entity.Property(e => e.SessionId) - .HasColumnName("sessionid") - .HasElementName("sessionid"); + entity.Property(e => e.Id).HasElementName(DbConstants.Columns.Id); + entity.Property(e => e.SessionId).HasElementName(DbConstants.Columns.SessionId); entity.Property(e => e.Timestamp) - .HasColumnName("timestamp") - .HasElementName("timestamp"); - - entity.Property(e => e.Username) - .HasColumnName("username") - .HasElementName("username"); - - entity.Property(e => e.HostUsername) - .HasColumnName("host_user") - .HasElementName("host_user"); - - entity.Property(e => e.RevitBuild) - .HasColumnName("revitbuild") - .HasElementName("revitbuild"); - - entity.Property(e => e.RevitVersion) - .HasColumnName("revit") - .HasElementName("revit"); - - entity.Property(e => e.PyRevitVersion) - .HasColumnName("pyrevit") - .HasElementName("pyrevit"); - - entity.Property(e => e.CloneName) - .HasColumnName("clone") - .HasElementName("clone"); - - entity.Property(e => e.IsDebug) - .HasColumnName("debug") - .HasElementName("debug"); - - entity.Property(e => e.IsConfig) - .HasColumnName("config") - .HasElementName("config"); - - entity.Property(e => e.IsExecFromGui) - .HasColumnName("from_gui") - .HasElementName("from_gui"); - - entity.Property(e => e.ExecId) - .HasColumnName("exec_id") - .HasElementName("exec_id"); + .HasElementName(DbConstants.Columns.Timestamp) + .HasBsonRepresentation(BsonType.DateTime); + + entity.Property(e => e.Username).HasElementName(DbConstants.Columns.Username); + entity.Property(e => e.HostUsername).HasElementName(DbConstants.Columns.HostUsername); + entity.Property(e => e.RevitBuild).HasElementName(DbConstants.Columns.RevitBuild); + entity.Property(e => e.RevitVersion).HasElementName(DbConstants.Columns.RevitVersion); + entity.Property(e => e.PyRevitVersion).HasElementName(DbConstants.Columns.PyRevitVersion); + entity.Property(e => e.CloneName).HasElementName(DbConstants.Columns.CloneName); + entity.Property(e => e.IsDebug).HasElementName(DbConstants.Columns.IsDebug); + entity.Property(e => e.IsConfig).HasElementName(DbConstants.Columns.IsConfig); + entity.Property(e => e.IsExecFromGui).HasElementName(DbConstants.Columns.IsExecFromGui); + entity.Property(e => e.ExecId).HasElementName(DbConstants.Columns.ExecId); entity.Property(e => e.ExecTimestamp) - .HasColumnName("exec_timestamp") - .HasElementName("exec_timestamp"); - - entity.Property(e => e.CommandBundle) - .HasColumnName("commandbundle") - .HasElementName("commandbundle"); - - entity.Property(e => e.CommandExtension) - .HasColumnName("commandextension") - .HasElementName("commandextension"); + .HasElementName(DbConstants.Columns.ExecTimestamp) + .HasBsonRepresentation(BsonType.DateTime); + + entity.Property(e => e.CommandBundle).HasElementName(DbConstants.Columns.CommandBundle); + entity.Property(e => e.CommandExtension).HasElementName(DbConstants.Columns.CommandExtension); + entity.Property(e => e.CommandName).HasElementName(DbConstants.Columns.CommandName); + entity.Property(e => e.CommandUniqueName).HasElementName(DbConstants.Columns.CommandUniqueName); + entity.Property(e => e.DocumentName).HasElementName(DbConstants.Columns.DocumentName); + entity.Property(e => e.DocumentPath).HasElementName(DbConstants.Columns.DocumentPath); + entity.Property(e => e.ResultCode).HasElementName(DbConstants.Columns.ResultCode); + entity.Property(e => e.ScriptPath).HasElementName(DbConstants.Columns.ScriptPath); + entity.Property(e => e.CommandResults).HasElementName(DbConstants.Columns.CommandResults); - entity.Property(e => e.CommandName) - .HasColumnName("commandname") - .HasElementName("commandname"); - - entity.Property(e => e.CommandUniqueName) - .HasColumnName("commanduniquename") - .HasElementName("commanduniquename"); + entity.OwnsOne(e => e.Trace, trace => + { + trace.Property(e => e.Message).HasElementName(DbConstants.Columns.TraceMessage); + trace.Property(e => e.Engine.Type).HasElementName(DbConstants.Columns.EngineType); + trace.Property(e => e.Engine.Version).HasElementName(DbConstants.Columns.EngineVersion); + trace.Property(e => e.Engine.Configs).HasElementName(DbConstants.Columns.EngineConfigs); + trace.Property(e => e.Engine.SysPaths).HasElementName(DbConstants.Columns.EngineSysPaths); + }); + }); - entity.Property(e => e.DocumentName) - .HasColumnName("docname") - .HasElementName("docname"); + modelBuilder.Entity(entity => + { + entity.ToCollection(DbConstants.Tables.Events); + entity.HasKey(e => e.Id); - entity.Property(e => e.DocumentPath) - .HasColumnName("docpath") - .HasElementName("docpath"); + entity.Property(e => e.Id).HasElementName(DbConstants.Columns.Id); + entity.Property(e => e.HandlerId).HasElementName(DbConstants.Columns.HandlerId); + entity.Property(e => e.EventType).HasElementName(DbConstants.Columns.EventType); + entity.Property(e => e.Status).HasElementName(DbConstants.Columns.Status); - entity.Property(e => e.ResultCode) - .HasColumnName("resultcode") - .HasElementName("resultcode"); + entity.Property(e => e.Timestamp) + .HasElementName(DbConstants.Columns.Timestamp) + .HasBsonRepresentation(BsonType.DateTime); + + entity.Property(e => e.Username).HasElementName(DbConstants.Columns.Username); + entity.Property(e => e.HostUsername).HasElementName(DbConstants.Columns.HostUsername); + entity.Property(e => e.RevitBuild).HasElementName(DbConstants.Columns.RevitBuild); + entity.Property(e => e.RevitVersion).HasElementName(DbConstants.Columns.RevitVersion); + entity.Property(e => e.Cancelled).HasElementName(DbConstants.Columns.Cancelled); + entity.Property(e => e.Cancellable).HasElementName(DbConstants.Columns.Cancellable); + entity.Property(e => e.DocumentId).HasElementName(DbConstants.Columns.DocumentId); + entity.Property(e => e.DocumentType).HasElementName(DbConstants.Columns.DocumentType); + entity.Property(e => e.DocumentTemplate).HasElementName(DbConstants.Columns.DocumentTemplate); + entity.Property(e => e.DocumentName).HasElementName(DbConstants.Columns.DocumentName); + entity.Property(e => e.DocumentPath).HasElementName(DbConstants.Columns.DocumentPath); + entity.Property(e => e.ProjectName).HasElementName(DbConstants.Columns.ProjectName); + entity.Property(e => e.ProjectNum).HasElementName(DbConstants.Columns.ProjectNum); + entity.Property(e => e.EventArgs).HasElementName(DbConstants.Columns.EventArgs); + }); + } - entity.Property(e => e.ScriptPath) - .HasColumnName("scriptpath") - .HasElementName("scriptpath"); + private void ConfigureSqlModel(ModelBuilder modelBuilder) + { + modelBuilder.Entity(entity => + { + entity.ToTable(DbConstants.Tables.Scripts); + entity.HasKey(e => e.Id); - entity.Property(e => e.CommandResults) - .HasColumnName("commandresults") - .HasElementName("commandresults"); + entity.Property(e => e.Id).HasColumnName(DbConstants.Columns.Id); + entity.Property(e => e.SessionId).HasColumnName(DbConstants.Columns.SessionId); + entity.Property(e => e.Timestamp).HasColumnName(DbConstants.Columns.Timestamp); + entity.Property(e => e.Username).HasColumnName(DbConstants.Columns.Username); + entity.Property(e => e.HostUsername).HasColumnName(DbConstants.Columns.HostUsername); + entity.Property(e => e.RevitBuild).HasColumnName(DbConstants.Columns.RevitBuild); + entity.Property(e => e.RevitVersion).HasColumnName(DbConstants.Columns.RevitVersion); + entity.Property(e => e.PyRevitVersion).HasColumnName(DbConstants.Columns.PyRevitVersion); + entity.Property(e => e.CloneName).HasColumnName(DbConstants.Columns.CloneName); + entity.Property(e => e.IsDebug).HasColumnName(DbConstants.Columns.IsDebug); + entity.Property(e => e.IsConfig).HasColumnName(DbConstants.Columns.IsConfig); + entity.Property(e => e.IsExecFromGui).HasColumnName(DbConstants.Columns.IsExecFromGui); + entity.Property(e => e.ExecId).HasColumnName(DbConstants.Columns.ExecId); + entity.Property(e => e.ExecTimestamp).HasColumnName(DbConstants.Columns.ExecTimestamp); + entity.Property(e => e.CommandBundle).HasColumnName(DbConstants.Columns.CommandBundle); + entity.Property(e => e.CommandExtension).HasColumnName(DbConstants.Columns.CommandExtension); + entity.Property(e => e.CommandName).HasColumnName(DbConstants.Columns.CommandName); + entity.Property(e => e.CommandUniqueName).HasColumnName(DbConstants.Columns.CommandUniqueName); + entity.Property(e => e.DocumentName).HasColumnName(DbConstants.Columns.DocumentName); + entity.Property(e => e.DocumentPath).HasColumnName(DbConstants.Columns.DocumentPath); + entity.Property(e => e.ResultCode).HasColumnName(DbConstants.Columns.ResultCode); + entity.Property(e => e.ScriptPath).HasColumnName(DbConstants.Columns.ScriptPath); + entity.Property(e => e.CommandResults).HasColumnName(DbConstants.Columns.CommandResults); entity.OwnsOne(e => e.Trace, trace => { - trace.Property(e => e.Message) - .HasColumnName("trace_message") - .HasElementName("trace_message"); - - trace.Property(e => e.Engine.Type) - .HasColumnName("engine_type") - .HasElementName("engine_type"); - - trace.Property(e => e.Engine.Version) - .HasColumnName("engine_configs") - .HasElementName("engine_configs"); - - trace.Property(e => e.Engine.Configs) - .HasColumnName("configs") - .HasElementName("configs"); + trace.Property(e => e.Message).HasColumnName(DbConstants.Columns.TraceMessage); + trace.Property(e => e.Engine.Type).HasColumnName(DbConstants.Columns.EngineType); + trace.Property(e => e.Engine.Version).HasColumnName(DbConstants.Columns.EngineVersion); + trace.Property(e => e.Engine.Configs).HasColumnName(DbConstants.Columns.EngineConfigs); trace.Property(e => e.Engine.SysPaths) - .HasColumnName("engine_syspath") - .HasElementName("engine_syspath") + .HasColumnName(DbConstants.Columns.EngineSysPaths) .HasConversion( v => v == null ? null : string.Join(";", v), v => string.IsNullOrEmpty(v) ? null : v.Split(";") @@ -269,106 +276,29 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) modelBuilder.Entity(entity => { - entity.ToTable("events"); - entity.ToCollection("events"); + entity.ToTable(DbConstants.Tables.Events); entity.HasKey(e => e.Id); - entity.Property(e => e.Id) - .HasColumnName("_id") - .HasElementName("_id"); - - entity.Property(e => e.HandlerId) - .HasColumnName("handler_id") - .HasElementName("handler_id"); - - entity.Property(e => e.EventType) - .HasColumnName("type") - .HasElementName("type"); - - entity.Property(e => e.Status) - .HasColumnName("status") - .HasElementName("status"); - - entity.Property(e => e.Timestamp) - .HasColumnName("timestamp") - .HasElementName("timestamp"); - - entity.Property(e => e.Username) - .HasColumnName("username") - .HasElementName("username"); - - entity.Property(e => e.HostUsername) - .HasColumnName("host_user") - .HasElementName("host_user"); - - entity.Property(e => e.RevitBuild) - .HasColumnName("revitbuild") - .HasElementName("revitbuild"); - - entity.Property(e => e.RevitVersion) - .HasColumnName("revit") - .HasElementName("revit"); - - entity.Property(e => e.Cancelled) - .HasColumnName("cancelled") - .HasElementName("cancelled"); - - entity.Property(e => e.Cancellable) - .HasColumnName("cancellable") - .HasElementName("cancellable"); - - entity.Property(e => e.DocumentId) - .HasColumnName("docid") - .HasElementName("docid"); - - entity.Property(e => e.DocumentType) - .HasColumnName("doctype") - .HasElementName("doctype"); - - entity.Property(e => e.DocumentTemplate) - .HasColumnName("doctemplate") - .HasElementName("doctemplate"); - - entity.Property(e => e.DocumentName) - .HasColumnName("docname") - .HasElementName("docname"); - - entity.Property(e => e.DocumentPath) - .HasColumnName("docpath") - .HasElementName("docpath"); - - entity.Property(e => e.ProjectName) - .HasColumnName("projectname") - .HasElementName("projectname"); - - entity.Property(e => e.ProjectNum) - .HasColumnName("projectnum") - .HasElementName("projectnum"); - - entity.Property(e => e.EventArgs) - .HasColumnName("args") - .HasElementName("args"); + entity.Property(e => e.Id).HasColumnName(DbConstants.Columns.Id); + entity.Property(e => e.HandlerId).HasColumnName(DbConstants.Columns.HandlerId); + entity.Property(e => e.EventType).HasColumnName(DbConstants.Columns.EventType); + entity.Property(e => e.Status).HasColumnName(DbConstants.Columns.Status); + entity.Property(e => e.Timestamp).HasColumnName(DbConstants.Columns.Timestamp); + entity.Property(e => e.Username).HasColumnName(DbConstants.Columns.Username); + entity.Property(e => e.HostUsername).HasColumnName(DbConstants.Columns.HostUsername); + entity.Property(e => e.RevitBuild).HasColumnName(DbConstants.Columns.RevitBuild); + entity.Property(e => e.RevitVersion).HasColumnName(DbConstants.Columns.RevitVersion); + entity.Property(e => e.Cancelled).HasColumnName(DbConstants.Columns.Cancelled); + entity.Property(e => e.Cancellable).HasColumnName(DbConstants.Columns.Cancellable); + entity.Property(e => e.DocumentId).HasColumnName(DbConstants.Columns.DocumentId); + entity.Property(e => e.DocumentType).HasColumnName(DbConstants.Columns.DocumentType); + entity.Property(e => e.DocumentTemplate).HasColumnName(DbConstants.Columns.DocumentTemplate); + entity.Property(e => e.DocumentName).HasColumnName(DbConstants.Columns.DocumentName); + entity.Property(e => e.DocumentPath).HasColumnName(DbConstants.Columns.DocumentPath); + entity.Property(e => e.ProjectName).HasColumnName(DbConstants.Columns.ProjectName); + entity.Property(e => e.ProjectNum).HasColumnName(DbConstants.Columns.ProjectNum); + entity.Property(e => e.EventArgs).HasColumnName(DbConstants.Columns.EventArgs); }); - - if (Database.ProviderName!.Equals("MongoDB.EntityFrameworkCore")) - { - modelBuilder.Entity(entity => - { - entity.Property(e => e.Timestamp) - .HasBsonRepresentation(BsonType.DateTime); - - entity.Property(e => e.ExecTimestamp) - .HasBsonRepresentation(BsonType.DateTime); - }); - - modelBuilder.Entity(entity => - { - entity.Property(e => e.Timestamp) - .HasBsonRepresentation(BsonType.DateTime); - }); - } - - base.OnModelCreating(modelBuilder); } } } \ No newline at end of file diff --git a/src/Telemetry.Api/Infrastructure/Persistence/DbConstants.cs b/src/Telemetry.Api/Infrastructure/Persistence/DbConstants.cs new file mode 100644 index 0000000..592e2b9 --- /dev/null +++ b/src/Telemetry.Api/Infrastructure/Persistence/DbConstants.cs @@ -0,0 +1,56 @@ +namespace Telemetry.Api.Infrastructure.Persistence +{ + internal static class DbConstants + { + public static class Tables + { + public const string Events = "events"; + public const string Scripts = "scripts"; + } + + public static class Columns + { + public const string Id = "_id"; + public const string SessionId = "sessionid"; + public const string Timestamp = "timestamp"; + public const string Username = "username"; + public const string HostUsername = "host_user"; + public const string RevitBuild = "revitbuild"; + public const string RevitVersion = "revit"; + public const string PyRevitVersion = "pyrevit"; + public const string CloneName = "clone"; + public const string IsDebug = "debug"; + public const string IsConfig = "config"; + public const string IsExecFromGui = "from_gui"; + public const string ExecId = "exec_id"; + public const string ExecTimestamp = "exec_timestamp"; + public const string CommandBundle = "commandbundle"; + public const string CommandExtension = "commandextension"; + public const string CommandName = "commandname"; + public const string CommandUniqueName = "commanduniquename"; + public const string DocumentName = "docname"; + public const string DocumentPath = "docpath"; + public const string ResultCode = "resultcode"; + public const string ScriptPath = "scriptpath"; + public const string CommandResults = "commandresults"; + + public const string TraceMessage = "trace_message"; + public const string EngineType = "engine_type"; + public const string EngineVersion = "engine_configs"; + public const string EngineConfigs = "configs"; + public const string EngineSysPaths = "engine_syspath"; + + public const string HandlerId = "handler_id"; + public const string EventType = "type"; + public const string Status = "status"; + public const string Cancelled = "cancelled"; + public const string Cancellable = "cancellable"; + public const string DocumentId = "docid"; + public const string DocumentType = "doctype"; + public const string DocumentTemplate = "doctemplate"; + public const string ProjectName = "projectname"; + public const string ProjectNum = "projectnum"; + public const string EventArgs = "args"; + } + } +} \ No newline at end of file diff --git a/tests/Telemetry.Api.UnitTests/Application/Mappings/TelemetryMappingExtensionsTests.cs b/tests/Telemetry.Api.UnitTests/Application/Mappings/TelemetryMappingExtensionsTests.cs index 03f54b7..ccd33ea 100644 --- a/tests/Telemetry.Api.UnitTests/Application/Mappings/TelemetryMappingExtensionsTests.cs +++ b/tests/Telemetry.Api.UnitTests/Application/Mappings/TelemetryMappingExtensionsTests.cs @@ -110,7 +110,6 @@ public async Task ScriptRecordDto_ToModel_ShouldMapCorrectly() // Assert await Assert.That(model.Id).IsNotEqualTo(Guid.Empty); await Assert.That(model.SessionId).IsEqualTo(dto.SessionId); - await Assert.That(model.Meta.SchemaVersion).IsEqualTo(dto.Meta.SchemaVersion); await Assert.That(model.Timestamp).IsEqualTo(dto.Timestamp); await Assert.That(model.Username).IsEqualTo(dto.Username); await Assert.That(model.HostUsername).IsEqualTo(dto.HostUsername); @@ -143,7 +142,6 @@ public async Task ScriptRecord_ToDto_ShouldMapCorrectly() { Id = Guid.NewGuid(), SessionId = Guid.NewGuid(), - Meta = new MetaRecord {SchemaVersion = new Version(2, 0)}, Timestamp = DateTimeOffset.Now, Username = "user", HostUsername = "host", @@ -176,7 +174,6 @@ public async Task ScriptRecord_ToDto_ShouldMapCorrectly() // Assert await Assert.That(dto.SessionId).IsEqualTo(model.SessionId); - await Assert.That(dto.Meta.SchemaVersion).IsEqualTo(model.Meta.SchemaVersion); await Assert.That(dto.Timestamp).IsEqualTo(model.Timestamp); await Assert.That(dto.Username).IsEqualTo(model.Username); await Assert.That(dto.HostUsername).IsEqualTo(model.HostUsername); @@ -233,7 +230,6 @@ public async Task EventRecordDto_ToModel_ShouldMapCorrectly() // Assert await Assert.That(model.Id).IsNotEqualTo(Guid.Empty); await Assert.That(model.HandlerId).IsEqualTo(dto.HandlerId); - await Assert.That(model.Meta.SchemaVersion).IsEqualTo(dto.Meta.SchemaVersion); await Assert.That(model.EventType).IsEqualTo(dto.EventType); await Assert.That(model.Status).IsEqualTo(dto.Status); await Assert.That(model.Timestamp).IsEqualTo(dto.Timestamp); @@ -260,7 +256,6 @@ public async Task EventRecord_ToDto_ShouldMapCorrectly() { Id = Guid.NewGuid(), HandlerId = Guid.NewGuid(), - Meta = new MetaRecord {SchemaVersion = new Version(2, 0)}, EventType = "DocOpened", Status = "Success", Timestamp = DateTimeOffset.Now, @@ -284,7 +279,6 @@ public async Task EventRecord_ToDto_ShouldMapCorrectly() // Assert await Assert.That(dto.HandlerId).IsEqualTo(model.HandlerId); - await Assert.That(dto.Meta.SchemaVersion).IsEqualTo(model.Meta.SchemaVersion); await Assert.That(dto.EventType).IsEqualTo(model.EventType); await Assert.That(dto.Status).IsEqualTo(model.Status); await Assert.That(dto.Timestamp).IsEqualTo(model.Timestamp); From b9af01619d9cf17ca249fc1603bf4fddaac38a4f Mon Sep 17 00:00:00 2001 From: dosymep Date: Mon, 6 Apr 2026 18:01:20 +0600 Subject: [PATCH 25/31] add nested properties to engine --- .../Persistence/ApplicationDbContext.cs | 47 +++++++++++++------ 1 file changed, 33 insertions(+), 14 deletions(-) diff --git a/src/Telemetry.Api/Infrastructure/Persistence/ApplicationDbContext.cs b/src/Telemetry.Api/Infrastructure/Persistence/ApplicationDbContext.cs index f08a764..5350632 100644 --- a/src/Telemetry.Api/Infrastructure/Persistence/ApplicationDbContext.cs +++ b/src/Telemetry.Api/Infrastructure/Persistence/ApplicationDbContext.cs @@ -4,6 +4,7 @@ using MongoDB.EntityFrameworkCore.Extensions; using System.Data; using System.Data.Common; +using System.Reflection; using System.Text.Json; using Telemetry.Api.Application.Interfaces; using Telemetry.Api.Domain.Models; @@ -104,6 +105,10 @@ public async Task GetDbVersionAsync(CancellationToken cancellationToken) else if (Database.IsInMemory()) { return "memorydb"; + } else if (Database.ProviderName!.Equals("MongoDB.EntityFrameworkCore")) + { + return $"EF Core lib version: " + + $"{typeof(MongoPropertyBuilderExtensions).Assembly.GetName().Version?.ToString() ?? "mongodb"}"; } if (query != null) @@ -189,10 +194,20 @@ private void ConfigureMongoDbModel(ModelBuilder modelBuilder) entity.OwnsOne(e => e.Trace, trace => { trace.Property(e => e.Message).HasElementName(DbConstants.Columns.TraceMessage); - trace.Property(e => e.Engine.Type).HasElementName(DbConstants.Columns.EngineType); - trace.Property(e => e.Engine.Version).HasElementName(DbConstants.Columns.EngineVersion); - trace.Property(e => e.Engine.Configs).HasElementName(DbConstants.Columns.EngineConfigs); - trace.Property(e => e.Engine.SysPaths).HasElementName(DbConstants.Columns.EngineSysPaths); + + trace.OwnsOne(e => e.Engine, engine => + { + engine.Property(e => e.Type).HasElementName(DbConstants.Columns.EngineType); + engine.Property(e => e.Version).HasElementName(DbConstants.Columns.EngineVersion); + engine.Property(e => e.Configs).HasElementName(DbConstants.Columns.EngineConfigs); + + engine.Property(e => e.SysPaths) + .HasElementName(DbConstants.Columns.EngineSysPaths) + .HasConversion( + v => v == null ? null : string.Join(";", v), + v => string.IsNullOrEmpty(v) ? null : v.Split(";") + ); + }); }); }); @@ -261,16 +276,20 @@ private void ConfigureSqlModel(ModelBuilder modelBuilder) entity.OwnsOne(e => e.Trace, trace => { trace.Property(e => e.Message).HasColumnName(DbConstants.Columns.TraceMessage); - trace.Property(e => e.Engine.Type).HasColumnName(DbConstants.Columns.EngineType); - trace.Property(e => e.Engine.Version).HasColumnName(DbConstants.Columns.EngineVersion); - trace.Property(e => e.Engine.Configs).HasColumnName(DbConstants.Columns.EngineConfigs); - - trace.Property(e => e.Engine.SysPaths) - .HasColumnName(DbConstants.Columns.EngineSysPaths) - .HasConversion( - v => v == null ? null : string.Join(";", v), - v => string.IsNullOrEmpty(v) ? null : v.Split(";") - ); + + trace.OwnsOne(e => e.Engine, engine => + { + engine.Property(e => e.Type).HasColumnName(DbConstants.Columns.EngineType); + engine.Property(e => e.Version).HasColumnName(DbConstants.Columns.EngineVersion); + engine.Property(e => e.Configs).HasColumnName(DbConstants.Columns.EngineConfigs); + + engine.Property(e => e.SysPaths) + .HasColumnName(DbConstants.Columns.EngineSysPaths) + .HasConversion( + v => v == null ? null : string.Join(";", v), + v => string.IsNullOrEmpty(v) ? null : v.Split(";") + ); + }); }); }); From 3458d3af5f13c2eb8acb487e849c45c0b3be09a9 Mon Sep 17 00:00:00 2001 From: dosymep Date: Mon, 6 Apr 2026 18:18:10 +0600 Subject: [PATCH 26/31] refactor: replace `DbConstants` with `PropertyNames` for improved consistency and modularity --- .../Application/DTOs/EngineInfoDto.cs | 9 +- .../Application/DTOs/EventRecordDto.cs | 37 ++--- .../Application/DTOs/ScriptRecordDto.cs | 47 +++--- .../Application/DTOs/TraceInfoDto.cs | 5 +- .../Domain/Constants/PropertyNames.cs | 131 ++++++++++++++++ src/Telemetry.Api/Domain/Models/EngineInfo.cs | 7 +- .../Domain/Models/EventRecord.cs | 22 +++ .../Domain/Models/ScriptRecord.cs | 28 +++- src/Telemetry.Api/Domain/Models/TraceInfo.cs | 5 +- .../Persistence/ApplicationDbContext.cs | 144 ++---------------- .../Infrastructure/Persistence/DbConstants.cs | 56 ------- 11 files changed, 251 insertions(+), 240 deletions(-) create mode 100644 src/Telemetry.Api/Domain/Constants/PropertyNames.cs delete mode 100644 src/Telemetry.Api/Infrastructure/Persistence/DbConstants.cs diff --git a/src/Telemetry.Api/Application/DTOs/EngineInfoDto.cs b/src/Telemetry.Api/Application/DTOs/EngineInfoDto.cs index 426abe1..edc6938 100644 --- a/src/Telemetry.Api/Application/DTOs/EngineInfoDto.cs +++ b/src/Telemetry.Api/Application/DTOs/EngineInfoDto.cs @@ -1,5 +1,6 @@ using System.ComponentModel.DataAnnotations; using System.Text.Json.Serialization; +using Telemetry.Api.Domain.Constants; using Telemetry.Api.JsonConverters; namespace Telemetry.Api.Application.DTOs @@ -14,7 +15,7 @@ public class EngineInfoDto ///
Engine types. /// [MaxLength(100)] - [JsonPropertyName("type")] + [JsonPropertyName(PropertyNames.EngineType)] public required string Type { get; init; } /// @@ -22,20 +23,20 @@ public class EngineInfoDto ///
Engines list. ///
[MaxLength(100)] - [JsonPropertyName("version")] + [JsonPropertyName(PropertyNames.EngineVersion)] public required string Version { get; init; } /// /// System paths using by script. /// - [JsonPropertyName("syspath")] + [JsonPropertyName(PropertyNames.EngineSysPaths)] public string[]? SysPath { get; init; } /// /// Dynamic script configs data. /// [MaxLength(8000)] - [JsonPropertyName("configs")] + [JsonPropertyName(PropertyNames.EngineConfigs)] [JsonConverter(typeof(DynamicDataJsonConverter))] public string? Configs { get; init; } } diff --git a/src/Telemetry.Api/Application/DTOs/EventRecordDto.cs b/src/Telemetry.Api/Application/DTOs/EventRecordDto.cs index 188b658..128d85c 100644 --- a/src/Telemetry.Api/Application/DTOs/EventRecordDto.cs +++ b/src/Telemetry.Api/Application/DTOs/EventRecordDto.cs @@ -1,5 +1,6 @@ using System.ComponentModel.DataAnnotations; using System.Text.Json.Serialization; +using Telemetry.Api.Domain.Constants; using Telemetry.Api.JsonConverters; namespace Telemetry.Api.Application.DTOs @@ -12,7 +13,7 @@ public class EventRecordDto /// /// Unique event id. /// - [JsonPropertyName("handler_id")] + [JsonPropertyName(PropertyNames.HandlerId)] public required Guid HandlerId { get; init; } /// @@ -25,7 +26,7 @@ public class EventRecordDto /// Event type name. /// [MaxLength(100)] - [JsonPropertyName("type")] + [JsonPropertyName(PropertyNames.EventType)] public required string EventType { get; init; } /// @@ -33,13 +34,13 @@ public class EventRecordDto /// status. /// [MaxLength(100)] - [JsonPropertyName("status")] + [JsonPropertyName(PropertyNames.Status)] public string? Status { get; init; } /// /// When event started. /// - [JsonPropertyName("timestamp")] + [JsonPropertyName(PropertyNames.Timestamp)] public required DateTimeOffset Timestamp { get; init; } /// @@ -47,7 +48,7 @@ public class EventRecordDto /// who use Autodesk Revit (sets in options). /// [MaxLength(100)] - [JsonPropertyName("username")] + [JsonPropertyName(PropertyNames.Username)] public required string Username { get; init; } /// @@ -55,7 +56,7 @@ public class EventRecordDto /// who logged in Windows. /// [MaxLength(100)] - [JsonPropertyName("host_user")] + [JsonPropertyName(PropertyNames.HostUsername)] public string? HostUsername { get; init; } /// @@ -64,7 +65,7 @@ public class EventRecordDto /// of the Autodesk Revit application. /// [MaxLength(100)] - [JsonPropertyName("revitbuild")] + [JsonPropertyName(PropertyNames.RevitBuild)] public required string RevitBuild { get; init; } /// @@ -73,7 +74,7 @@ public class EventRecordDto /// of the Revit application. /// [MaxLength(100)] - [JsonPropertyName("revit")] + [JsonPropertyName(PropertyNames.RevitVersion)] public required string RevitVersion { get; init; } /// @@ -81,7 +82,7 @@ public class EventRecordDto ///
RevitAPIEventArgs /// IsCancelled method. ///
- [JsonPropertyName("cancelled")] + [JsonPropertyName(PropertyNames.Cancelled)] public bool? Cancelled { get; init; } /// @@ -89,7 +90,7 @@ public class EventRecordDto ///
RevitAPIEventArgs /// Cancellable property. ///
- [JsonPropertyName("cancellable")] + [JsonPropertyName(PropertyNames.Cancellable)] public bool? Cancellable { get; init; } /// @@ -99,7 +100,7 @@ public class EventRecordDto ///
DocumentClosedEventArgs /// DocumentId property. ///
- [JsonPropertyName("docid")] + [JsonPropertyName(PropertyNames.DocumentId)] public int DocumentId { get; init; } /// @@ -112,7 +113,7 @@ public class EventRecordDto /// DocumentType property. /// [MaxLength(100)] - [JsonPropertyName("doctype")] + [JsonPropertyName(PropertyNames.DocumentType)] public string? DocumentType { get; init; } /// @@ -121,14 +122,14 @@ public class EventRecordDto /// Template property. /// [MaxLength(100)] - [JsonPropertyName("doctemplate")] + [JsonPropertyName(PropertyNames.DocumentTemplate)] public string? DocumentTemplate { get; init; } /// /// Document Title property. /// [MaxLength(250)] - [JsonPropertyName("docname")] + [JsonPropertyName(PropertyNames.DocumentName)] public string? DocumentName { get; init; } /// @@ -136,7 +137,7 @@ public class EventRecordDto /// property. /// [MaxLength(1024)] - [JsonPropertyName("docpath")] + [JsonPropertyName(PropertyNames.DocumentPath)] public string? DocumentPath { get; init; } /// @@ -144,7 +145,7 @@ public class EventRecordDto /// (BuiltInParameter.PROJECT_NAME). /// [MaxLength(250)] - [JsonPropertyName("projectname")] + [JsonPropertyName(PropertyNames.ProjectName)] public string? ProjectName { get; init; } /// @@ -152,14 +153,14 @@ public class EventRecordDto /// (BuiltInParameter.PROJECT_NUMBER). /// [MaxLength(100)] - [JsonPropertyName("projectnum")] + [JsonPropertyName(PropertyNames.ProjectNum)] public string? ProjectNum { get; init; } /// /// Dynamic event args data. /// [MaxLength(8000)] - [JsonPropertyName("args")] + [JsonPropertyName(PropertyNames.EventArgs)] [JsonConverter(typeof(DynamicDataJsonConverter))] public string? EventArgs { get; init; } } diff --git a/src/Telemetry.Api/Application/DTOs/ScriptRecordDto.cs b/src/Telemetry.Api/Application/DTOs/ScriptRecordDto.cs index 9a65581..2b9df64 100644 --- a/src/Telemetry.Api/Application/DTOs/ScriptRecordDto.cs +++ b/src/Telemetry.Api/Application/DTOs/ScriptRecordDto.cs @@ -1,5 +1,6 @@ using System.ComponentModel.DataAnnotations; using System.Text.Json.Serialization; +using Telemetry.Api.Domain.Constants; using Telemetry.Api.JsonConverters; namespace Telemetry.Api.Application.DTOs @@ -12,7 +13,7 @@ public class ScriptRecordDto /// /// Unique session id (created when revit is opened). /// - [JsonPropertyName("sessionid")] + [JsonPropertyName(PropertyNames.SessionId)] public required Guid SessionId { get; init; } /// @@ -24,7 +25,7 @@ public class ScriptRecordDto /// /// When script started. /// - [JsonPropertyName("timestamp")] + [JsonPropertyName(PropertyNames.Timestamp)] public required DateTimeOffset Timestamp { get; init; } /// @@ -32,7 +33,7 @@ public class ScriptRecordDto /// who use Autodesk Revit (sets in options). /// [MaxLength(100)] - [JsonPropertyName("username")] + [JsonPropertyName(PropertyNames.Username)] public required string Username { get; init; } /// @@ -40,7 +41,7 @@ public class ScriptRecordDto /// who logged in Windows. /// [MaxLength(100)] - [JsonPropertyName("host_user")] + [JsonPropertyName(PropertyNames.HostUsername)] public string? HostUsername { get; init; } /// @@ -49,7 +50,7 @@ public class ScriptRecordDto /// of the Autodesk Revit application. /// [MaxLength(100)] - [JsonPropertyName("revitbuild")] + [JsonPropertyName(PropertyNames.RevitBuild)] public required string RevitBuild { get; init; } /// @@ -58,14 +59,14 @@ public class ScriptRecordDto /// of the Revit application. /// [MaxLength(100)] - [JsonPropertyName("revit")] + [JsonPropertyName(PropertyNames.RevitVersion)] public required string RevitVersion { get; init; } /// /// pyrevit build version. /// [MaxLength(100)] - [JsonPropertyName("pyrevit")] + [JsonPropertyName(PropertyNames.PyRevitVersion)] public required string PyRevitVersion { get; init; } /// @@ -73,7 +74,7 @@ public class ScriptRecordDto /// clone name. /// [MaxLength(100)] - [JsonPropertyName("clone")] + [JsonPropertyName(PropertyNames.CloneName)] public required string CloneName { get; init; } /// @@ -84,68 +85,68 @@ public class ScriptRecordDto /// mode /// . /// - [JsonPropertyName("debug")] + [JsonPropertyName(PropertyNames.IsDebug)] public bool IsDebug { get; init; } /// /// pyrevit /// config mode. /// - [JsonPropertyName("config")] + [JsonPropertyName(PropertyNames.IsConfig)] public bool IsConfig { get; init; } /// /// If script was run from GUI (Click Revit Ribbon) , otherwise . /// - [JsonPropertyName("from_gui")] + [JsonPropertyName(PropertyNames.IsExecFromGui)] public bool IsExecFromGui { get; init; } /// /// Unique execution id. /// [MaxLength(100)] - [JsonPropertyName("exec_id")] + [JsonPropertyName(PropertyNames.ExecId)] public required string ExecId { get; init; } /// /// When script executed. /// - [JsonPropertyName("exec_timestamp")] + [JsonPropertyName(PropertyNames.ExecTimestamp)] public required DateTimeOffset ExecTimestamp { get; init; } /// /// Command bundle name. /// [MaxLength(250)] - [JsonPropertyName("commandbundle")] + [JsonPropertyName(PropertyNames.CommandBundle)] public required string CommandBundle { get; init; } /// /// Command extension name. /// [MaxLength(250)] - [JsonPropertyName("commandextension")] + [JsonPropertyName(PropertyNames.CommandExtension)] public required string CommandExtension { get; init; } /// /// Command name. /// [MaxLength(250)] - [JsonPropertyName("commandname")] + [JsonPropertyName(PropertyNames.CommandName)] public required string CommandName { get; init; } /// /// Command unique name. /// [MaxLength(500)] - [JsonPropertyName("commanduniquename")] + [JsonPropertyName(PropertyNames.CommandUniqueName)] public required string CommandUniqueName { get; init; } /// /// Document Title property. /// [MaxLength(250)] - [JsonPropertyName("docname")] + [JsonPropertyName(PropertyNames.DocumentName)] public string? DocumentName { get; init; } /// @@ -153,7 +154,7 @@ public class ScriptRecordDto /// property. /// [MaxLength(1024)] - [JsonPropertyName("docpath")] + [JsonPropertyName(PropertyNames.DocumentPath)] public string? DocumentPath { get; init; } /// @@ -161,27 +162,27 @@ public class ScriptRecordDto ///
ResultCode /// enumeration. ///
- [JsonPropertyName("resultcode")] + [JsonPropertyName(PropertyNames.ResultCode)] public int ResultCode { get; init; } /// /// Executed script path. /// [MaxLength(1024)] - [JsonPropertyName("scriptpath")] + [JsonPropertyName(PropertyNames.ScriptPath)] public required string ScriptPath { get; init; } /// /// Information about execution. /// - [JsonPropertyName("trace")] + [JsonPropertyName(PropertyNames.Trace)] public required TraceInfoDto Trace { get; init; } /// /// Additional command results. /// [MaxLength(8000)] - [JsonPropertyName("commandresults")] + [JsonPropertyName(PropertyNames.CommandResults)] [JsonConverter(typeof(DynamicDataJsonConverter))] public string? CommandResults { get; init; } } diff --git a/src/Telemetry.Api/Application/DTOs/TraceInfoDto.cs b/src/Telemetry.Api/Application/DTOs/TraceInfoDto.cs index 32fa4cd..eebeb6f 100644 --- a/src/Telemetry.Api/Application/DTOs/TraceInfoDto.cs +++ b/src/Telemetry.Api/Application/DTOs/TraceInfoDto.cs @@ -1,5 +1,6 @@ using System.ComponentModel.DataAnnotations; using System.Text.Json.Serialization; +using Telemetry.Api.Domain.Constants; namespace Telemetry.Api.Application.DTOs { @@ -13,13 +14,13 @@ public class TraceInfoDto /// message. ///
[MaxLength(8000)] - [JsonPropertyName("message")] + [JsonPropertyName(PropertyNames.TraceMessage)] public required string Message { get; init; } /// /// Script engine information. /// - [JsonPropertyName("engine")] + [JsonPropertyName(PropertyNames.Engine)] public required EngineInfoDto Engine { get; init; } } } \ No newline at end of file diff --git a/src/Telemetry.Api/Domain/Constants/PropertyNames.cs b/src/Telemetry.Api/Domain/Constants/PropertyNames.cs new file mode 100644 index 0000000..e9ccb31 --- /dev/null +++ b/src/Telemetry.Api/Domain/Constants/PropertyNames.cs @@ -0,0 +1,131 @@ +namespace Telemetry.Api.Domain.Constants +{ + /// + /// Property names constants. + /// + public static class PropertyNames + { + /// Unique identifier. + public const string Id = "_id"; + + /// Session identifier. + public const string SessionId = "sessionid"; + + /// Timestamp. + public const string Timestamp = "timestamp"; + + /// Username. + public const string Username = "username"; + + /// Host username. + public const string HostUsername = "host_user"; + + /// Revit build version. + public const string RevitBuild = "revitbuild"; + + /// Revit version. + public const string RevitVersion = "revit"; + + /// pyRevit version. + public const string PyRevitVersion = "pyrevit"; + + /// Clone name. + public const string CloneName = "clone"; + + /// Is debug mode. + public const string IsDebug = "debug"; + + /// Is config mode. + public const string IsConfig = "config"; + + /// Is executed from GUI. + public const string IsExecFromGui = "from_gui"; + + /// Execution identifier. + public const string ExecId = "exec_id"; + + /// Execution timestamp. + public const string ExecTimestamp = "exec_timestamp"; + + /// Command bundle. + public const string CommandBundle = "commandbundle"; + + /// Command extension. + public const string CommandExtension = "commandextension"; + + /// Command name. + public const string CommandName = "commandname"; + + /// Command unique name. + public const string CommandUniqueName = "commanduniquename"; + + /// Document name. + public const string DocumentName = "docname"; + + /// Document path. + public const string DocumentPath = "docpath"; + + /// Result code. + public const string ResultCode = "resultcode"; + + /// Script path. + public const string ScriptPath = "scriptpath"; + + /// Command results. + public const string CommandResults = "commandresults"; + + /// Trace information. + public const string Trace = "trace"; + + /// Trace message. + public const string TraceMessage = "message"; + + /// Engine information. + public const string Engine = "engine"; + + /// Engine type. + public const string EngineType = "type"; + + /// Engine version. + public const string EngineVersion = "version"; + + /// Engine configs. + public const string EngineConfigs = "configs"; + + /// Engine system paths. + public const string EngineSysPaths = "syspath"; + + /// Handler identifier. + public const string HandlerId = "handler_id"; + + /// Event type. + public const string EventType = "type"; + + /// Status. + public const string Status = "status"; + + /// Is cancelled. + public const string Cancelled = "cancelled"; + + /// Is cancellable. + public const string Cancellable = "cancellable"; + + /// Document identifier. + public const string DocumentId = "docid"; + + /// Document type. + public const string DocumentType = "doctype"; + + /// Document template. + public const string DocumentTemplate = "doctemplate"; + + /// Project name. + public const string ProjectName = "projectname"; + + /// Project number. + public const string ProjectNum = "projectnum"; + + /// Event arguments. + public const string EventArgs = "args"; + } +} \ No newline at end of file diff --git a/src/Telemetry.Api/Domain/Models/EngineInfo.cs b/src/Telemetry.Api/Domain/Models/EngineInfo.cs index 31dd97b..d2b9e73 100644 --- a/src/Telemetry.Api/Domain/Models/EngineInfo.cs +++ b/src/Telemetry.Api/Domain/Models/EngineInfo.cs @@ -1,6 +1,7 @@ -using MongoDB.Bson.Serialization.Attributes; using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; using System.Text.Json.Serialization; +using Telemetry.Api.Domain.Constants; using Telemetry.Api.JsonConverters; namespace Telemetry.Api.Domain.Models @@ -15,6 +16,7 @@ public class EngineInfo ///
Engine types. /// [MaxLength(100)] + [Column(PropertyNames.EngineType)] public required string Type { get; init; } /// @@ -22,17 +24,20 @@ public class EngineInfo ///
Engines list. ///
[MaxLength(100)] + [Column(PropertyNames.EngineVersion)] public required string Version { get; init; } /// /// System paths using by script. /// + [Column(PropertyNames.EngineSysPaths)] public string[]? SysPaths { get; init; } /// /// Dynamic script configs data. /// [MaxLength(8000)] + [Column(PropertyNames.EngineConfigs)] public string? Configs { get; init; } } } \ No newline at end of file diff --git a/src/Telemetry.Api/Domain/Models/EventRecord.cs b/src/Telemetry.Api/Domain/Models/EventRecord.cs index 2267290..bc6348f 100644 --- a/src/Telemetry.Api/Domain/Models/EventRecord.cs +++ b/src/Telemetry.Api/Domain/Models/EventRecord.cs @@ -2,28 +2,34 @@ using MongoDB.Bson.Serialization.Attributes; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; +using Telemetry.Api.Domain.Constants; namespace Telemetry.Api.Domain.Models { /// /// Event record information. /// + [Table("events")] public class EventRecord { /// /// Event id. /// + [Key] + [Column(PropertyNames.Id)] public Guid Id { get; init; } /// /// Unique event id. /// + [Column(PropertyNames.HandlerId)] public Guid HandlerId { get; init; } /// /// Event type name. /// [MaxLength(100)] + [Column(PropertyNames.EventType)] public required string EventType { get; init; } /// @@ -31,11 +37,13 @@ public class EventRecord /// status. /// [MaxLength(100)] + [Column(PropertyNames.Status)] public string? Status { get; init; } /// /// When event started. /// + [Column(PropertyNames.Timestamp)] public DateTimeOffset Timestamp { get; init; } /// @@ -43,6 +51,7 @@ public class EventRecord /// who use Autodesk Revit (sets in options). /// [MaxLength(100)] + [Column(PropertyNames.Username)] public required string Username { get; init; } /// @@ -50,6 +59,7 @@ public class EventRecord /// who logged in Windows. /// [MaxLength(100)] + [Column(PropertyNames.HostUsername)] public string? HostUsername { get; init; } /// @@ -58,6 +68,7 @@ public class EventRecord /// of the Autodesk Revit application. /// [MaxLength(100)] + [Column(PropertyNames.RevitBuild)] public required string RevitBuild { get; init; } /// @@ -66,6 +77,7 @@ public class EventRecord /// of the Revit application. /// [MaxLength(100)] + [Column(PropertyNames.RevitVersion)] public required string RevitVersion { get; init; } /// @@ -73,6 +85,7 @@ public class EventRecord ///
RevitAPIEventArgs /// IsCancelled method. ///
+ [Column(PropertyNames.Cancelled)] public bool? Cancelled { get; init; } /// @@ -80,6 +93,7 @@ public class EventRecord ///
RevitAPIEventArgs /// Cancellable property. ///
+ [Column(PropertyNames.Cancellable)] public bool? Cancellable { get; init; } /// @@ -89,6 +103,7 @@ public class EventRecord ///
DocumentClosedEventArgs /// DocumentId property. ///
+ [Column(PropertyNames.DocumentId)] public int DocumentId { get; init; } /// @@ -101,6 +116,7 @@ public class EventRecord /// DocumentType property. /// [MaxLength(100)] + [Column(PropertyNames.DocumentType)] public string? DocumentType { get; init; } /// @@ -109,12 +125,14 @@ public class EventRecord /// Template property. /// [MaxLength(100)] + [Column(PropertyNames.DocumentTemplate)] public string? DocumentTemplate { get; init; } /// /// Document Title property. /// [MaxLength(250)] + [Column(PropertyNames.DocumentName)] public string? DocumentName { get; init; } /// @@ -122,6 +140,7 @@ public class EventRecord /// property. /// [MaxLength(1024)] + [Column(PropertyNames.DocumentPath)] public string? DocumentPath { get; init; } /// @@ -129,6 +148,7 @@ public class EventRecord /// (BuiltInParameter.PROJECT_NAME). /// [MaxLength(250)] + [Column(PropertyNames.ProjectName)] public string? ProjectName { get; init; } /// @@ -136,12 +156,14 @@ public class EventRecord /// (BuiltInParameter.PROJECT_NUMBER). /// [MaxLength(100)] + [Column(PropertyNames.ProjectNum)] public string? ProjectNum { get; init; } /// /// Dynamic event args data. /// [MaxLength(8000)] + [Column(PropertyNames.EventArgs)] public string? EventArgs { get; init; } } } \ No newline at end of file diff --git a/src/Telemetry.Api/Domain/Models/ScriptRecord.cs b/src/Telemetry.Api/Domain/Models/ScriptRecord.cs index 4f9bde6..55d8995 100644 --- a/src/Telemetry.Api/Domain/Models/ScriptRecord.cs +++ b/src/Telemetry.Api/Domain/Models/ScriptRecord.cs @@ -3,6 +3,7 @@ using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using System.Text.Json.Serialization; +using Telemetry.Api.Domain.Constants; using Telemetry.Api.JsonConverters; namespace Telemetry.Api.Domain.Models @@ -10,21 +11,26 @@ namespace Telemetry.Api.Domain.Models /// /// Script record information. /// + [Table("scripts")] public class ScriptRecord { /// /// Scripts id. /// + [Key] + [Column(PropertyNames.Id)] public Guid Id { get; init; } /// /// Unique session id (created when revit is opened). /// + [Column(PropertyNames.SessionId)] public Guid SessionId { get; init; } /// /// When script started. /// + [Column(PropertyNames.Timestamp)] public DateTimeOffset Timestamp { get; init; } /// @@ -32,6 +38,7 @@ public class ScriptRecord /// who use Autodesk Revit (sets in options). /// [MaxLength(100)] + [Column(PropertyNames.Username)] public required string Username { get; init; } /// @@ -39,6 +46,7 @@ public class ScriptRecord /// who logged in Windows. /// [MaxLength(100)] + [Column(PropertyNames.HostUsername)] public string? HostUsername { get; init; } /// @@ -47,6 +55,7 @@ public class ScriptRecord /// of the Autodesk Revit application. /// [MaxLength(100)] + [Column(PropertyNames.RevitBuild)] public required string RevitBuild { get; init; } /// @@ -55,12 +64,14 @@ public class ScriptRecord /// of the Revit application. /// [MaxLength(100)] + [Column(PropertyNames.RevitVersion)] public required string RevitVersion { get; init; } /// /// pyrevit build version. /// [MaxLength(100)] + [Column(PropertyNames.PyRevitVersion)] public required string PyRevitVersion { get; init; } /// @@ -68,6 +79,7 @@ public class ScriptRecord /// clone name. /// [MaxLength(100)] + [Column(PropertyNames.CloneName)] public required string CloneName { get; init; } /// @@ -78,59 +90,68 @@ public class ScriptRecord /// mode /// . /// + [Column(PropertyNames.IsDebug)] public bool IsDebug { get; init; } /// /// pyrevit /// config mode. /// - [BsonElement("config")] + [Column(PropertyNames.IsConfig)] public bool IsConfig { get; init; } /// /// If script was run from GUI (Click Revit Ribbon) , otherwise . /// + [Column(PropertyNames.IsExecFromGui)] public bool IsExecFromGui { get; init; } /// /// Unique execution id. /// [MaxLength(100)] + [Column(PropertyNames.ExecId)] public required string ExecId { get; init; } /// /// When script executed. /// + [Column(PropertyNames.ExecTimestamp)] public DateTimeOffset ExecTimestamp { get; init; } /// /// Command bundle name. /// [MaxLength(250)] + [Column(PropertyNames.CommandBundle)] public required string CommandBundle { get; init; } /// /// Command extension name. /// [MaxLength(250)] + [Column(PropertyNames.CommandExtension)] public required string CommandExtension { get; init; } /// /// Command name. /// [MaxLength(250)] + [Column(PropertyNames.CommandName)] public required string CommandName { get; init; } /// /// Command unique name. /// [MaxLength(500)] + [Column(PropertyNames.CommandUniqueName)] public required string CommandUniqueName { get; init; } /// /// Document Title property. /// [MaxLength(250)] + [Column(PropertyNames.DocumentName)] public string? DocumentName { get; init; } /// @@ -138,6 +159,7 @@ public class ScriptRecord /// property. /// [MaxLength(1024)] + [Column(PropertyNames.DocumentPath)] public string? DocumentPath { get; init; } /// @@ -145,23 +167,27 @@ public class ScriptRecord ///
ResultCode /// enumeration. ///
+ [Column(PropertyNames.ResultCode)] public int ResultCode { get; init; } /// /// Executed script path. /// [MaxLength(1024)] + [Column(PropertyNames.ScriptPath)] public required string ScriptPath { get; init; } /// /// Information about execution. /// + [Column(PropertyNames.Trace)] public required TraceInfo Trace { get; init; } /// /// Additional command results. /// [MaxLength(8000)] + [Column(PropertyNames.CommandResults)] public string? CommandResults { get; init; } } } \ No newline at end of file diff --git a/src/Telemetry.Api/Domain/Models/TraceInfo.cs b/src/Telemetry.Api/Domain/Models/TraceInfo.cs index 6195a52..f2b7d88 100644 --- a/src/Telemetry.Api/Domain/Models/TraceInfo.cs +++ b/src/Telemetry.Api/Domain/Models/TraceInfo.cs @@ -1,6 +1,7 @@ -using MongoDB.Bson.Serialization.Attributes; using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; using System.Text.Json.Serialization; +using Telemetry.Api.Domain.Constants; namespace Telemetry.Api.Domain.Models { @@ -14,11 +15,13 @@ public class TraceInfo /// message. /// [MaxLength(8000)] + [Column(PropertyNames.TraceMessage)] public required string Message { get; init; } /// /// Script engine information. /// + [Column(PropertyNames.Engine)] public required EngineInfo Engine { get; init; } } } \ No newline at end of file diff --git a/src/Telemetry.Api/Infrastructure/Persistence/ApplicationDbContext.cs b/src/Telemetry.Api/Infrastructure/Persistence/ApplicationDbContext.cs index 5350632..c1680d7 100644 --- a/src/Telemetry.Api/Infrastructure/Persistence/ApplicationDbContext.cs +++ b/src/Telemetry.Api/Infrastructure/Persistence/ApplicationDbContext.cs @@ -7,6 +7,7 @@ using System.Reflection; using System.Text.Json; using Telemetry.Api.Application.Interfaces; +using Telemetry.Api.Domain.Constants; using Telemetry.Api.Domain.Models; namespace Telemetry.Api.Infrastructure.Persistence @@ -105,7 +106,8 @@ public async Task GetDbVersionAsync(CancellationToken cancellationToken) else if (Database.IsInMemory()) { return "memorydb"; - } else if (Database.ProviderName!.Equals("MongoDB.EntityFrameworkCore")) + } + else if (Database.ProviderName!.Equals("MongoDB.EntityFrameworkCore")) { return $"EF Core lib version: " + $"{typeof(MongoPropertyBuilderExtensions).Assembly.GetName().Version?.ToString() ?? "mongodb"}"; @@ -152,139 +154,39 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) base.OnModelCreating(modelBuilder); } - private void ConfigureMongoDbModel(ModelBuilder modelBuilder) + private static void ConfigureMongoDbModel(ModelBuilder modelBuilder) { modelBuilder.Entity(entity => { - entity.ToCollection(DbConstants.Tables.Scripts); - entity.HasKey(e => e.Id); - - entity.Property(e => e.Id).HasElementName(DbConstants.Columns.Id); - entity.Property(e => e.SessionId).HasElementName(DbConstants.Columns.SessionId); - entity.Property(e => e.Timestamp) - .HasElementName(DbConstants.Columns.Timestamp) .HasBsonRepresentation(BsonType.DateTime); - - entity.Property(e => e.Username).HasElementName(DbConstants.Columns.Username); - entity.Property(e => e.HostUsername).HasElementName(DbConstants.Columns.HostUsername); - entity.Property(e => e.RevitBuild).HasElementName(DbConstants.Columns.RevitBuild); - entity.Property(e => e.RevitVersion).HasElementName(DbConstants.Columns.RevitVersion); - entity.Property(e => e.PyRevitVersion).HasElementName(DbConstants.Columns.PyRevitVersion); - entity.Property(e => e.CloneName).HasElementName(DbConstants.Columns.CloneName); - entity.Property(e => e.IsDebug).HasElementName(DbConstants.Columns.IsDebug); - entity.Property(e => e.IsConfig).HasElementName(DbConstants.Columns.IsConfig); - entity.Property(e => e.IsExecFromGui).HasElementName(DbConstants.Columns.IsExecFromGui); - entity.Property(e => e.ExecId).HasElementName(DbConstants.Columns.ExecId); - entity.Property(e => e.ExecTimestamp) - .HasElementName(DbConstants.Columns.ExecTimestamp) .HasBsonRepresentation(BsonType.DateTime); - - entity.Property(e => e.CommandBundle).HasElementName(DbConstants.Columns.CommandBundle); - entity.Property(e => e.CommandExtension).HasElementName(DbConstants.Columns.CommandExtension); - entity.Property(e => e.CommandName).HasElementName(DbConstants.Columns.CommandName); - entity.Property(e => e.CommandUniqueName).HasElementName(DbConstants.Columns.CommandUniqueName); - entity.Property(e => e.DocumentName).HasElementName(DbConstants.Columns.DocumentName); - entity.Property(e => e.DocumentPath).HasElementName(DbConstants.Columns.DocumentPath); - entity.Property(e => e.ResultCode).HasElementName(DbConstants.Columns.ResultCode); - entity.Property(e => e.ScriptPath).HasElementName(DbConstants.Columns.ScriptPath); - entity.Property(e => e.CommandResults).HasElementName(DbConstants.Columns.CommandResults); - - entity.OwnsOne(e => e.Trace, trace => - { - trace.Property(e => e.Message).HasElementName(DbConstants.Columns.TraceMessage); - - trace.OwnsOne(e => e.Engine, engine => - { - engine.Property(e => e.Type).HasElementName(DbConstants.Columns.EngineType); - engine.Property(e => e.Version).HasElementName(DbConstants.Columns.EngineVersion); - engine.Property(e => e.Configs).HasElementName(DbConstants.Columns.EngineConfigs); - - engine.Property(e => e.SysPaths) - .HasElementName(DbConstants.Columns.EngineSysPaths) - .HasConversion( - v => v == null ? null : string.Join(";", v), - v => string.IsNullOrEmpty(v) ? null : v.Split(";") - ); - }); - }); }); modelBuilder.Entity(entity => { - entity.ToCollection(DbConstants.Tables.Events); - entity.HasKey(e => e.Id); - - entity.Property(e => e.Id).HasElementName(DbConstants.Columns.Id); - entity.Property(e => e.HandlerId).HasElementName(DbConstants.Columns.HandlerId); - entity.Property(e => e.EventType).HasElementName(DbConstants.Columns.EventType); - entity.Property(e => e.Status).HasElementName(DbConstants.Columns.Status); - entity.Property(e => e.Timestamp) - .HasElementName(DbConstants.Columns.Timestamp) .HasBsonRepresentation(BsonType.DateTime); - - entity.Property(e => e.Username).HasElementName(DbConstants.Columns.Username); - entity.Property(e => e.HostUsername).HasElementName(DbConstants.Columns.HostUsername); - entity.Property(e => e.RevitBuild).HasElementName(DbConstants.Columns.RevitBuild); - entity.Property(e => e.RevitVersion).HasElementName(DbConstants.Columns.RevitVersion); - entity.Property(e => e.Cancelled).HasElementName(DbConstants.Columns.Cancelled); - entity.Property(e => e.Cancellable).HasElementName(DbConstants.Columns.Cancellable); - entity.Property(e => e.DocumentId).HasElementName(DbConstants.Columns.DocumentId); - entity.Property(e => e.DocumentType).HasElementName(DbConstants.Columns.DocumentType); - entity.Property(e => e.DocumentTemplate).HasElementName(DbConstants.Columns.DocumentTemplate); - entity.Property(e => e.DocumentName).HasElementName(DbConstants.Columns.DocumentName); - entity.Property(e => e.DocumentPath).HasElementName(DbConstants.Columns.DocumentPath); - entity.Property(e => e.ProjectName).HasElementName(DbConstants.Columns.ProjectName); - entity.Property(e => e.ProjectNum).HasElementName(DbConstants.Columns.ProjectNum); - entity.Property(e => e.EventArgs).HasElementName(DbConstants.Columns.EventArgs); }); } - private void ConfigureSqlModel(ModelBuilder modelBuilder) + private static void ConfigureSqlModel(ModelBuilder modelBuilder) { modelBuilder.Entity(entity => { - entity.ToTable(DbConstants.Tables.Scripts); - entity.HasKey(e => e.Id); - - entity.Property(e => e.Id).HasColumnName(DbConstants.Columns.Id); - entity.Property(e => e.SessionId).HasColumnName(DbConstants.Columns.SessionId); - entity.Property(e => e.Timestamp).HasColumnName(DbConstants.Columns.Timestamp); - entity.Property(e => e.Username).HasColumnName(DbConstants.Columns.Username); - entity.Property(e => e.HostUsername).HasColumnName(DbConstants.Columns.HostUsername); - entity.Property(e => e.RevitBuild).HasColumnName(DbConstants.Columns.RevitBuild); - entity.Property(e => e.RevitVersion).HasColumnName(DbConstants.Columns.RevitVersion); - entity.Property(e => e.PyRevitVersion).HasColumnName(DbConstants.Columns.PyRevitVersion); - entity.Property(e => e.CloneName).HasColumnName(DbConstants.Columns.CloneName); - entity.Property(e => e.IsDebug).HasColumnName(DbConstants.Columns.IsDebug); - entity.Property(e => e.IsConfig).HasColumnName(DbConstants.Columns.IsConfig); - entity.Property(e => e.IsExecFromGui).HasColumnName(DbConstants.Columns.IsExecFromGui); - entity.Property(e => e.ExecId).HasColumnName(DbConstants.Columns.ExecId); - entity.Property(e => e.ExecTimestamp).HasColumnName(DbConstants.Columns.ExecTimestamp); - entity.Property(e => e.CommandBundle).HasColumnName(DbConstants.Columns.CommandBundle); - entity.Property(e => e.CommandExtension).HasColumnName(DbConstants.Columns.CommandExtension); - entity.Property(e => e.CommandName).HasColumnName(DbConstants.Columns.CommandName); - entity.Property(e => e.CommandUniqueName).HasColumnName(DbConstants.Columns.CommandUniqueName); - entity.Property(e => e.DocumentName).HasColumnName(DbConstants.Columns.DocumentName); - entity.Property(e => e.DocumentPath).HasColumnName(DbConstants.Columns.DocumentPath); - entity.Property(e => e.ResultCode).HasColumnName(DbConstants.Columns.ResultCode); - entity.Property(e => e.ScriptPath).HasColumnName(DbConstants.Columns.ScriptPath); - entity.Property(e => e.CommandResults).HasColumnName(DbConstants.Columns.CommandResults); - entity.OwnsOne(e => e.Trace, trace => { - trace.Property(e => e.Message).HasColumnName(DbConstants.Columns.TraceMessage); + trace.Property(e => e.Message).HasColumnName(PropertyNames.TraceMessage); trace.OwnsOne(e => e.Engine, engine => { - engine.Property(e => e.Type).HasColumnName(DbConstants.Columns.EngineType); - engine.Property(e => e.Version).HasColumnName(DbConstants.Columns.EngineVersion); - engine.Property(e => e.Configs).HasColumnName(DbConstants.Columns.EngineConfigs); + engine.Property(e => e.Type).HasColumnName(PropertyNames.EngineType); + engine.Property(e => e.Version).HasColumnName(PropertyNames.EngineVersion); + engine.Property(e => e.Configs).HasColumnName(PropertyNames.EngineConfigs); engine.Property(e => e.SysPaths) - .HasColumnName(DbConstants.Columns.EngineSysPaths) + .HasColumnName(PropertyNames.EngineSysPaths) .HasConversion( v => v == null ? null : string.Join(";", v), v => string.IsNullOrEmpty(v) ? null : v.Split(";") @@ -292,32 +194,6 @@ private void ConfigureSqlModel(ModelBuilder modelBuilder) }); }); }); - - modelBuilder.Entity(entity => - { - entity.ToTable(DbConstants.Tables.Events); - entity.HasKey(e => e.Id); - - entity.Property(e => e.Id).HasColumnName(DbConstants.Columns.Id); - entity.Property(e => e.HandlerId).HasColumnName(DbConstants.Columns.HandlerId); - entity.Property(e => e.EventType).HasColumnName(DbConstants.Columns.EventType); - entity.Property(e => e.Status).HasColumnName(DbConstants.Columns.Status); - entity.Property(e => e.Timestamp).HasColumnName(DbConstants.Columns.Timestamp); - entity.Property(e => e.Username).HasColumnName(DbConstants.Columns.Username); - entity.Property(e => e.HostUsername).HasColumnName(DbConstants.Columns.HostUsername); - entity.Property(e => e.RevitBuild).HasColumnName(DbConstants.Columns.RevitBuild); - entity.Property(e => e.RevitVersion).HasColumnName(DbConstants.Columns.RevitVersion); - entity.Property(e => e.Cancelled).HasColumnName(DbConstants.Columns.Cancelled); - entity.Property(e => e.Cancellable).HasColumnName(DbConstants.Columns.Cancellable); - entity.Property(e => e.DocumentId).HasColumnName(DbConstants.Columns.DocumentId); - entity.Property(e => e.DocumentType).HasColumnName(DbConstants.Columns.DocumentType); - entity.Property(e => e.DocumentTemplate).HasColumnName(DbConstants.Columns.DocumentTemplate); - entity.Property(e => e.DocumentName).HasColumnName(DbConstants.Columns.DocumentName); - entity.Property(e => e.DocumentPath).HasColumnName(DbConstants.Columns.DocumentPath); - entity.Property(e => e.ProjectName).HasColumnName(DbConstants.Columns.ProjectName); - entity.Property(e => e.ProjectNum).HasColumnName(DbConstants.Columns.ProjectNum); - entity.Property(e => e.EventArgs).HasColumnName(DbConstants.Columns.EventArgs); - }); } } } \ No newline at end of file diff --git a/src/Telemetry.Api/Infrastructure/Persistence/DbConstants.cs b/src/Telemetry.Api/Infrastructure/Persistence/DbConstants.cs deleted file mode 100644 index 592e2b9..0000000 --- a/src/Telemetry.Api/Infrastructure/Persistence/DbConstants.cs +++ /dev/null @@ -1,56 +0,0 @@ -namespace Telemetry.Api.Infrastructure.Persistence -{ - internal static class DbConstants - { - public static class Tables - { - public const string Events = "events"; - public const string Scripts = "scripts"; - } - - public static class Columns - { - public const string Id = "_id"; - public const string SessionId = "sessionid"; - public const string Timestamp = "timestamp"; - public const string Username = "username"; - public const string HostUsername = "host_user"; - public const string RevitBuild = "revitbuild"; - public const string RevitVersion = "revit"; - public const string PyRevitVersion = "pyrevit"; - public const string CloneName = "clone"; - public const string IsDebug = "debug"; - public const string IsConfig = "config"; - public const string IsExecFromGui = "from_gui"; - public const string ExecId = "exec_id"; - public const string ExecTimestamp = "exec_timestamp"; - public const string CommandBundle = "commandbundle"; - public const string CommandExtension = "commandextension"; - public const string CommandName = "commandname"; - public const string CommandUniqueName = "commanduniquename"; - public const string DocumentName = "docname"; - public const string DocumentPath = "docpath"; - public const string ResultCode = "resultcode"; - public const string ScriptPath = "scriptpath"; - public const string CommandResults = "commandresults"; - - public const string TraceMessage = "trace_message"; - public const string EngineType = "engine_type"; - public const string EngineVersion = "engine_configs"; - public const string EngineConfigs = "configs"; - public const string EngineSysPaths = "engine_syspath"; - - public const string HandlerId = "handler_id"; - public const string EventType = "type"; - public const string Status = "status"; - public const string Cancelled = "cancelled"; - public const string Cancellable = "cancellable"; - public const string DocumentId = "docid"; - public const string DocumentType = "doctype"; - public const string DocumentTemplate = "doctemplate"; - public const string ProjectName = "projectname"; - public const string ProjectNum = "projectnum"; - public const string EventArgs = "args"; - } - } -} \ No newline at end of file From d7d55bf2eeb7b91ef9e7ca91ddf344464328c7e8 Mon Sep 17 00:00:00 2001 From: dosymep Date: Mon, 6 Apr 2026 18:20:07 +0600 Subject: [PATCH 27/31] rename data base --- .env.example | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.env.example b/.env.example index 61f5471..3983971 100644 --- a/.env.example +++ b/.env.example @@ -7,20 +7,20 @@ ORACLE_APP_USER='oracle' ORACLE_APP_USER_PASSWORD='9%8bphDFOj4P' # Postgres -POSTGRES_DB=telemetry +POSTGRES_DB=pyrevit-telemetry POSTGRES_USER='postgres' POSTGRES_PASSWORD='iBT|vC857AoS' # MSSQL MSSQL_ACCEPT_EULA=Y -MSSQL_DATABASE_NAME=telemetry +MSSQL_DATABASE_NAME=pyrevit-telemetry MSSQL_USER='sa' MSSQL_SA_PASSWORD='AwbW~PNM3NxH' # SQLite -SQLITE_DATABASE_NAME=telemetry +SQLITE_DATABASE_NAME=pyrevit-telemetry # MongoDB -MONGODB_DATABASE_NAME=telemetry +MONGODB_DATABASE_NAME=pyrevit-telemetry MONGODB_ROOT_USER='mongodb' MONGODB_ROOT_PASSWORD='xF?iqMJhZj$R' \ No newline at end of file From 5beffd9b4390f535e84f4a1b3ff97b356303a479 Mon Sep 17 00:00:00 2001 From: dosymep Date: Mon, 6 Apr 2026 18:21:41 +0600 Subject: [PATCH 28/31] remove old migrations --- .../20260330090657_InitOracle.Designer.cs | 271 --------------- .../Migrations/20260330090657_InitOracle.cs | 90 ----- ...402141604_AddCancellableOracle.Designer.cs | 272 --------------- .../20260402141604_AddCancellableOracle.cs | 28 -- ...101958_UpdateDynamicDataOracle.Designer.cs | 321 ------------------ .../20260406101958_UpdateDynamicDataOracle.cs | 90 ----- .../ApplicationDbContextModelSnapshot.cs | 318 ----------------- .../20260330090711_InitPostgres.Designer.cs | 271 --------------- .../Migrations/20260330090711_InitPostgres.cs | 90 ----- ...2141612_AddCancellablePostgres.Designer.cs | 272 --------------- .../20260402141612_AddCancellablePostgres.cs | 28 -- ...2030_UpdateDynamicDataPostgres.Designer.cs | 321 ------------------ ...0260406102030_UpdateDynamicDataPostgres.cs | 90 ----- .../ApplicationDbContextModelSnapshot.cs | 318 ----------------- .../20260330090733_InitSqlServer.Designer.cs | 271 --------------- .../20260330090733_InitSqlServer.cs | 90 ----- ...141635_AddCancellableSqlServer.Designer.cs | 272 --------------- .../20260402141635_AddCancellableSqlServer.cs | 28 -- ...100_UpdateDynamicDataSqlServer.Designer.cs | 321 ------------------ ...260406102100_UpdateDynamicDataSqlServer.cs | 90 ----- .../ApplicationDbContextModelSnapshot.cs | 318 ----------------- .../20260330090723_InitSqlite.Designer.cs | 266 --------------- .../Migrations/20260330090723_InitSqlite.cs | 90 ----- ...402141622_AddCancellableSqlite.Designer.cs | 267 --------------- .../20260402141622_AddCancellableSqlite.cs | 28 -- ...102040_UpdateDynamicDataSqlite.Designer.cs | 316 ----------------- .../20260406102040_UpdateDynamicDataSqlite.cs | 90 ----- .../ApplicationDbContextModelSnapshot.cs | 313 ----------------- 28 files changed, 5540 deletions(-) delete mode 100644 src/Telemetry.Migrations.Oracle/Migrations/20260330090657_InitOracle.Designer.cs delete mode 100644 src/Telemetry.Migrations.Oracle/Migrations/20260330090657_InitOracle.cs delete mode 100644 src/Telemetry.Migrations.Oracle/Migrations/20260402141604_AddCancellableOracle.Designer.cs delete mode 100644 src/Telemetry.Migrations.Oracle/Migrations/20260402141604_AddCancellableOracle.cs delete mode 100644 src/Telemetry.Migrations.Oracle/Migrations/20260406101958_UpdateDynamicDataOracle.Designer.cs delete mode 100644 src/Telemetry.Migrations.Oracle/Migrations/20260406101958_UpdateDynamicDataOracle.cs delete mode 100644 src/Telemetry.Migrations.Oracle/Migrations/ApplicationDbContextModelSnapshot.cs delete mode 100644 src/Telemetry.Migrations.Postgres/Migrations/20260330090711_InitPostgres.Designer.cs delete mode 100644 src/Telemetry.Migrations.Postgres/Migrations/20260330090711_InitPostgres.cs delete mode 100644 src/Telemetry.Migrations.Postgres/Migrations/20260402141612_AddCancellablePostgres.Designer.cs delete mode 100644 src/Telemetry.Migrations.Postgres/Migrations/20260402141612_AddCancellablePostgres.cs delete mode 100644 src/Telemetry.Migrations.Postgres/Migrations/20260406102030_UpdateDynamicDataPostgres.Designer.cs delete mode 100644 src/Telemetry.Migrations.Postgres/Migrations/20260406102030_UpdateDynamicDataPostgres.cs delete mode 100644 src/Telemetry.Migrations.Postgres/Migrations/ApplicationDbContextModelSnapshot.cs delete mode 100644 src/Telemetry.Migrations.SqlServer/Migrations/20260330090733_InitSqlServer.Designer.cs delete mode 100644 src/Telemetry.Migrations.SqlServer/Migrations/20260330090733_InitSqlServer.cs delete mode 100644 src/Telemetry.Migrations.SqlServer/Migrations/20260402141635_AddCancellableSqlServer.Designer.cs delete mode 100644 src/Telemetry.Migrations.SqlServer/Migrations/20260402141635_AddCancellableSqlServer.cs delete mode 100644 src/Telemetry.Migrations.SqlServer/Migrations/20260406102100_UpdateDynamicDataSqlServer.Designer.cs delete mode 100644 src/Telemetry.Migrations.SqlServer/Migrations/20260406102100_UpdateDynamicDataSqlServer.cs delete mode 100644 src/Telemetry.Migrations.SqlServer/Migrations/ApplicationDbContextModelSnapshot.cs delete mode 100644 src/Telemetry.Migrations.Sqlite/Migrations/20260330090723_InitSqlite.Designer.cs delete mode 100644 src/Telemetry.Migrations.Sqlite/Migrations/20260330090723_InitSqlite.cs delete mode 100644 src/Telemetry.Migrations.Sqlite/Migrations/20260402141622_AddCancellableSqlite.Designer.cs delete mode 100644 src/Telemetry.Migrations.Sqlite/Migrations/20260402141622_AddCancellableSqlite.cs delete mode 100644 src/Telemetry.Migrations.Sqlite/Migrations/20260406102040_UpdateDynamicDataSqlite.Designer.cs delete mode 100644 src/Telemetry.Migrations.Sqlite/Migrations/20260406102040_UpdateDynamicDataSqlite.cs delete mode 100644 src/Telemetry.Migrations.Sqlite/Migrations/ApplicationDbContextModelSnapshot.cs diff --git a/src/Telemetry.Migrations.Oracle/Migrations/20260330090657_InitOracle.Designer.cs b/src/Telemetry.Migrations.Oracle/Migrations/20260330090657_InitOracle.Designer.cs deleted file mode 100644 index 2d3e912..0000000 --- a/src/Telemetry.Migrations.Oracle/Migrations/20260330090657_InitOracle.Designer.cs +++ /dev/null @@ -1,271 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Oracle.EntityFrameworkCore.Metadata; -using Telemetry.Api.Infrastructure.Persistence; - -#nullable disable - -namespace Telemetry.Migrations.Oracle.Migrations -{ - [DbContext(typeof(ApplicationDbContext))] - [Migration("20260330090657_InitOracle")] - partial class InitOracle - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "10.0.5") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - OracleModelBuilderExtensions.UseIdentityColumns(modelBuilder); - - modelBuilder.Entity("Telemetry.Api.Domain.Models.EventRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("RAW(16)") - .HasColumnName("id"); - - b.Property("Cancellable") - .HasColumnType("BOOLEAN"); - - b.Property("Cancelled") - .HasColumnType("BOOLEAN") - .HasColumnName("cancelled"); - - b.Property("DocumentId") - .HasColumnType("NUMBER(10)") - .HasColumnName("docid"); - - b.Property("DocumentName") - .HasMaxLength(250) - .HasColumnType("NVARCHAR2(250)") - .HasColumnName("docname"); - - b.Property("DocumentPath") - .HasMaxLength(1024) - .HasColumnType("NVARCHAR2(1024)") - .HasColumnName("docpath"); - - b.Property("DocumentTemplate") - .HasMaxLength(100) - .HasColumnType("NVARCHAR2(100)") - .HasColumnName("doctemplate"); - - b.Property("DocumentType") - .HasMaxLength(100) - .HasColumnType("NVARCHAR2(100)") - .HasColumnName("doctype"); - - b.Property("EventArgs") - .HasMaxLength(8000) - .HasColumnType("NCLOB") - .HasColumnName("args"); - - b.Property("EventType") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("NVARCHAR2(100)") - .HasColumnName("type"); - - b.Property("HandlerId") - .HasColumnType("RAW(16)") - .HasColumnName("handler_id"); - - b.Property("HostUsername") - .HasMaxLength(100) - .HasColumnType("NVARCHAR2(100)") - .HasColumnName("host_user"); - - b.Property("Meta") - .IsRequired() - .HasColumnType("NVARCHAR2(2000)") - .HasColumnName("meta"); - - b.Property("ProjectName") - .HasMaxLength(250) - .HasColumnType("NVARCHAR2(250)") - .HasColumnName("projectname"); - - b.Property("ProjectNum") - .HasMaxLength(100) - .HasColumnType("NVARCHAR2(100)") - .HasColumnName("projectnum"); - - b.Property("RevitBuild") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("NVARCHAR2(100)") - .HasColumnName("revitbuild"); - - b.Property("RevitVersion") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("NVARCHAR2(100)") - .HasColumnName("revit"); - - b.Property("Status") - .HasMaxLength(100) - .HasColumnType("NVARCHAR2(100)") - .HasColumnName("status"); - - b.Property("Timestamp") - .HasColumnType("TIMESTAMP(7) WITH TIME ZONE") - .HasColumnName("timestamp"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("NVARCHAR2(100)") - .HasColumnName("username"); - - b.HasKey("Id"); - - b.ToTable("event_record", (string)null); - }); - - modelBuilder.Entity("Telemetry.Api.Domain.Models.ScriptRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("RAW(16)") - .HasColumnName("id"); - - b.Property("CloneName") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("NVARCHAR2(100)") - .HasColumnName("clone"); - - b.Property("CommandBundle") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("NVARCHAR2(250)") - .HasColumnName("commandbundle"); - - b.Property("CommandExtension") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("NVARCHAR2(250)") - .HasColumnName("commandextension"); - - b.Property("CommandName") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("NVARCHAR2(250)") - .HasColumnName("commandname"); - - b.Property("CommandResults") - .HasMaxLength(8000) - .HasColumnType("NCLOB") - .HasColumnName("commandresults"); - - b.Property("CommandUniqueName") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("NVARCHAR2(500)") - .HasColumnName("commanduniquename"); - - b.Property("DocumentName") - .HasMaxLength(250) - .HasColumnType("NVARCHAR2(250)") - .HasColumnName("docname"); - - b.Property("DocumentPath") - .HasMaxLength(1024) - .HasColumnType("NVARCHAR2(1024)") - .HasColumnName("docpath"); - - b.Property("ExecId") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("NVARCHAR2(100)") - .HasColumnName("exec_id"); - - b.Property("ExecTimestamp") - .HasColumnType("TIMESTAMP(7) WITH TIME ZONE") - .HasColumnName("exec_timestamp"); - - b.Property("HostUsername") - .HasMaxLength(100) - .HasColumnType("NVARCHAR2(100)") - .HasColumnName("host_user"); - - b.Property("IsConfig") - .HasColumnType("BOOLEAN") - .HasColumnName("config"); - - b.Property("IsDebug") - .HasColumnType("BOOLEAN") - .HasColumnName("debug"); - - b.Property("IsExecFromGui") - .HasColumnType("BOOLEAN") - .HasColumnName("from_gui"); - - b.Property("Meta") - .IsRequired() - .HasColumnType("NVARCHAR2(2000)") - .HasColumnName("meta"); - - b.Property("PyRevitVersion") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("NVARCHAR2(100)") - .HasColumnName("pyrevit"); - - b.Property("ResultCode") - .HasColumnType("NUMBER(10)") - .HasColumnName("resultcode"); - - b.Property("RevitBuild") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("NVARCHAR2(100)") - .HasColumnName("revitbuild"); - - b.Property("RevitVersion") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("NVARCHAR2(100)") - .HasColumnName("revit"); - - b.Property("ScriptPath") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("NVARCHAR2(1024)") - .HasColumnName("scriptpath"); - - b.Property("SessionId") - .HasColumnType("RAW(16)") - .HasColumnName("sessionid"); - - b.Property("Timestamp") - .HasColumnType("TIMESTAMP(7) WITH TIME ZONE") - .HasColumnName("timestamp"); - - b.Property("Trace") - .IsRequired() - .HasColumnType("NVARCHAR2(2000)") - .HasColumnName("trace"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("NVARCHAR2(100)") - .HasColumnName("username"); - - b.HasKey("Id"); - - b.ToTable("script_record", (string)null); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Telemetry.Migrations.Oracle/Migrations/20260330090657_InitOracle.cs b/src/Telemetry.Migrations.Oracle/Migrations/20260330090657_InitOracle.cs deleted file mode 100644 index 47879bb..0000000 --- a/src/Telemetry.Migrations.Oracle/Migrations/20260330090657_InitOracle.cs +++ /dev/null @@ -1,90 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Telemetry.Migrations.Oracle.Migrations -{ - /// - public partial class InitOracle : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "event_record", - columns: table => new - { - id = table.Column(type: "RAW(16)", nullable: false), - handler_id = table.Column(type: "RAW(16)", nullable: false), - meta = table.Column(type: "NVARCHAR2(2000)", nullable: false), - type = table.Column(type: "NVARCHAR2(100)", maxLength: 100, nullable: false), - status = table.Column(type: "NVARCHAR2(100)", maxLength: 100, nullable: true), - timestamp = table.Column(type: "TIMESTAMP(7) WITH TIME ZONE", nullable: false), - username = table.Column(type: "NVARCHAR2(100)", maxLength: 100, nullable: false), - host_user = table.Column(type: "NVARCHAR2(100)", maxLength: 100, nullable: true), - revitbuild = table.Column(type: "NVARCHAR2(100)", maxLength: 100, nullable: false), - revit = table.Column(type: "NVARCHAR2(100)", maxLength: 100, nullable: false), - cancelled = table.Column(type: "BOOLEAN", nullable: true), - Cancellable = table.Column(type: "BOOLEAN", nullable: true), - docid = table.Column(type: "NUMBER(10)", nullable: false), - doctype = table.Column(type: "NVARCHAR2(100)", maxLength: 100, nullable: true), - doctemplate = table.Column(type: "NVARCHAR2(100)", maxLength: 100, nullable: true), - docname = table.Column(type: "NVARCHAR2(250)", maxLength: 250, nullable: true), - docpath = table.Column(type: "NVARCHAR2(1024)", maxLength: 1024, nullable: true), - projectname = table.Column(type: "NVARCHAR2(250)", maxLength: 250, nullable: true), - projectnum = table.Column(type: "NVARCHAR2(100)", maxLength: 100, nullable: true), - args = table.Column(type: "NCLOB", maxLength: 8000, nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_event_record", x => x.id); - }); - - migrationBuilder.CreateTable( - name: "script_record", - columns: table => new - { - id = table.Column(type: "RAW(16)", nullable: false), - sessionid = table.Column(type: "RAW(16)", nullable: false), - meta = table.Column(type: "NVARCHAR2(2000)", nullable: false), - timestamp = table.Column(type: "TIMESTAMP(7) WITH TIME ZONE", nullable: false), - username = table.Column(type: "NVARCHAR2(100)", maxLength: 100, nullable: false), - host_user = table.Column(type: "NVARCHAR2(100)", maxLength: 100, nullable: true), - revitbuild = table.Column(type: "NVARCHAR2(100)", maxLength: 100, nullable: false), - revit = table.Column(type: "NVARCHAR2(100)", maxLength: 100, nullable: false), - pyrevit = table.Column(type: "NVARCHAR2(100)", maxLength: 100, nullable: false), - clone = table.Column(type: "NVARCHAR2(100)", maxLength: 100, nullable: false), - debug = table.Column(type: "BOOLEAN", nullable: false), - config = table.Column(type: "BOOLEAN", nullable: false), - from_gui = table.Column(type: "BOOLEAN", nullable: false), - exec_id = table.Column(type: "NVARCHAR2(100)", maxLength: 100, nullable: false), - exec_timestamp = table.Column(type: "TIMESTAMP(7) WITH TIME ZONE", nullable: false), - commandbundle = table.Column(type: "NVARCHAR2(250)", maxLength: 250, nullable: false), - commandextension = table.Column(type: "NVARCHAR2(250)", maxLength: 250, nullable: false), - commandname = table.Column(type: "NVARCHAR2(250)", maxLength: 250, nullable: false), - commanduniquename = table.Column(type: "NVARCHAR2(500)", maxLength: 500, nullable: false), - docname = table.Column(type: "NVARCHAR2(250)", maxLength: 250, nullable: true), - docpath = table.Column(type: "NVARCHAR2(1024)", maxLength: 1024, nullable: true), - resultcode = table.Column(type: "NUMBER(10)", nullable: false), - scriptpath = table.Column(type: "NVARCHAR2(1024)", maxLength: 1024, nullable: false), - trace = table.Column(type: "NVARCHAR2(2000)", nullable: false), - commandresults = table.Column(type: "NCLOB", maxLength: 8000, nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_script_record", x => x.id); - }); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "event_record"); - - migrationBuilder.DropTable( - name: "script_record"); - } - } -} diff --git a/src/Telemetry.Migrations.Oracle/Migrations/20260402141604_AddCancellableOracle.Designer.cs b/src/Telemetry.Migrations.Oracle/Migrations/20260402141604_AddCancellableOracle.Designer.cs deleted file mode 100644 index 6622f86..0000000 --- a/src/Telemetry.Migrations.Oracle/Migrations/20260402141604_AddCancellableOracle.Designer.cs +++ /dev/null @@ -1,272 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Oracle.EntityFrameworkCore.Metadata; -using Telemetry.Api.Infrastructure.Persistence; - -#nullable disable - -namespace Telemetry.Migrations.Oracle.Migrations -{ - [DbContext(typeof(ApplicationDbContext))] - [Migration("20260402141604_AddCancellableOracle")] - partial class AddCancellableOracle - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "10.0.5") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - OracleModelBuilderExtensions.UseIdentityColumns(modelBuilder); - - modelBuilder.Entity("Telemetry.Api.Domain.Models.EventRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("RAW(16)") - .HasColumnName("id"); - - b.Property("Cancellable") - .HasColumnType("BOOLEAN") - .HasColumnName("cancellable"); - - b.Property("Cancelled") - .HasColumnType("BOOLEAN") - .HasColumnName("cancelled"); - - b.Property("DocumentId") - .HasColumnType("NUMBER(10)") - .HasColumnName("docid"); - - b.Property("DocumentName") - .HasMaxLength(250) - .HasColumnType("NVARCHAR2(250)") - .HasColumnName("docname"); - - b.Property("DocumentPath") - .HasMaxLength(1024) - .HasColumnType("NVARCHAR2(1024)") - .HasColumnName("docpath"); - - b.Property("DocumentTemplate") - .HasMaxLength(100) - .HasColumnType("NVARCHAR2(100)") - .HasColumnName("doctemplate"); - - b.Property("DocumentType") - .HasMaxLength(100) - .HasColumnType("NVARCHAR2(100)") - .HasColumnName("doctype"); - - b.Property("EventArgs") - .HasMaxLength(8000) - .HasColumnType("NCLOB") - .HasColumnName("args"); - - b.Property("EventType") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("NVARCHAR2(100)") - .HasColumnName("type"); - - b.Property("HandlerId") - .HasColumnType("RAW(16)") - .HasColumnName("handler_id"); - - b.Property("HostUsername") - .HasMaxLength(100) - .HasColumnType("NVARCHAR2(100)") - .HasColumnName("host_user"); - - b.Property("Meta") - .IsRequired() - .HasColumnType("NVARCHAR2(2000)") - .HasColumnName("meta"); - - b.Property("ProjectName") - .HasMaxLength(250) - .HasColumnType("NVARCHAR2(250)") - .HasColumnName("projectname"); - - b.Property("ProjectNum") - .HasMaxLength(100) - .HasColumnType("NVARCHAR2(100)") - .HasColumnName("projectnum"); - - b.Property("RevitBuild") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("NVARCHAR2(100)") - .HasColumnName("revitbuild"); - - b.Property("RevitVersion") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("NVARCHAR2(100)") - .HasColumnName("revit"); - - b.Property("Status") - .HasMaxLength(100) - .HasColumnType("NVARCHAR2(100)") - .HasColumnName("status"); - - b.Property("Timestamp") - .HasColumnType("TIMESTAMP(7) WITH TIME ZONE") - .HasColumnName("timestamp"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("NVARCHAR2(100)") - .HasColumnName("username"); - - b.HasKey("Id"); - - b.ToTable("event_record", (string)null); - }); - - modelBuilder.Entity("Telemetry.Api.Domain.Models.ScriptRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("RAW(16)") - .HasColumnName("id"); - - b.Property("CloneName") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("NVARCHAR2(100)") - .HasColumnName("clone"); - - b.Property("CommandBundle") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("NVARCHAR2(250)") - .HasColumnName("commandbundle"); - - b.Property("CommandExtension") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("NVARCHAR2(250)") - .HasColumnName("commandextension"); - - b.Property("CommandName") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("NVARCHAR2(250)") - .HasColumnName("commandname"); - - b.Property("CommandResults") - .HasMaxLength(8000) - .HasColumnType("NCLOB") - .HasColumnName("commandresults"); - - b.Property("CommandUniqueName") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("NVARCHAR2(500)") - .HasColumnName("commanduniquename"); - - b.Property("DocumentName") - .HasMaxLength(250) - .HasColumnType("NVARCHAR2(250)") - .HasColumnName("docname"); - - b.Property("DocumentPath") - .HasMaxLength(1024) - .HasColumnType("NVARCHAR2(1024)") - .HasColumnName("docpath"); - - b.Property("ExecId") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("NVARCHAR2(100)") - .HasColumnName("exec_id"); - - b.Property("ExecTimestamp") - .HasColumnType("TIMESTAMP(7) WITH TIME ZONE") - .HasColumnName("exec_timestamp"); - - b.Property("HostUsername") - .HasMaxLength(100) - .HasColumnType("NVARCHAR2(100)") - .HasColumnName("host_user"); - - b.Property("IsConfig") - .HasColumnType("BOOLEAN") - .HasColumnName("config"); - - b.Property("IsDebug") - .HasColumnType("BOOLEAN") - .HasColumnName("debug"); - - b.Property("IsExecFromGui") - .HasColumnType("BOOLEAN") - .HasColumnName("from_gui"); - - b.Property("Meta") - .IsRequired() - .HasColumnType("NVARCHAR2(2000)") - .HasColumnName("meta"); - - b.Property("PyRevitVersion") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("NVARCHAR2(100)") - .HasColumnName("pyrevit"); - - b.Property("ResultCode") - .HasColumnType("NUMBER(10)") - .HasColumnName("resultcode"); - - b.Property("RevitBuild") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("NVARCHAR2(100)") - .HasColumnName("revitbuild"); - - b.Property("RevitVersion") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("NVARCHAR2(100)") - .HasColumnName("revit"); - - b.Property("ScriptPath") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("NVARCHAR2(1024)") - .HasColumnName("scriptpath"); - - b.Property("SessionId") - .HasColumnType("RAW(16)") - .HasColumnName("sessionid"); - - b.Property("Timestamp") - .HasColumnType("TIMESTAMP(7) WITH TIME ZONE") - .HasColumnName("timestamp"); - - b.Property("Trace") - .IsRequired() - .HasColumnType("NVARCHAR2(2000)") - .HasColumnName("trace"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("NVARCHAR2(100)") - .HasColumnName("username"); - - b.HasKey("Id"); - - b.ToTable("script_record", (string)null); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Telemetry.Migrations.Oracle/Migrations/20260402141604_AddCancellableOracle.cs b/src/Telemetry.Migrations.Oracle/Migrations/20260402141604_AddCancellableOracle.cs deleted file mode 100644 index 67066bf..0000000 --- a/src/Telemetry.Migrations.Oracle/Migrations/20260402141604_AddCancellableOracle.cs +++ /dev/null @@ -1,28 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Telemetry.Migrations.Oracle.Migrations -{ - /// - public partial class AddCancellableOracle : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.RenameColumn( - name: "Cancellable", - table: "event_record", - newName: "cancellable"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.RenameColumn( - name: "cancellable", - table: "event_record", - newName: "Cancellable"); - } - } -} diff --git a/src/Telemetry.Migrations.Oracle/Migrations/20260406101958_UpdateDynamicDataOracle.Designer.cs b/src/Telemetry.Migrations.Oracle/Migrations/20260406101958_UpdateDynamicDataOracle.Designer.cs deleted file mode 100644 index 08069d2..0000000 --- a/src/Telemetry.Migrations.Oracle/Migrations/20260406101958_UpdateDynamicDataOracle.Designer.cs +++ /dev/null @@ -1,321 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Oracle.EntityFrameworkCore.Metadata; -using Telemetry.Api.Infrastructure.Persistence; - -#nullable disable - -namespace Telemetry.Migrations.Oracle.Migrations -{ - [DbContext(typeof(ApplicationDbContext))] - [Migration("20260406101958_UpdateDynamicDataOracle")] - partial class UpdateDynamicDataOracle - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "10.0.5") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - OracleModelBuilderExtensions.UseIdentityColumns(modelBuilder); - - modelBuilder.Entity("Telemetry.Api.Domain.Models.EventRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("RAW(16)") - .HasColumnName("_id") - .HasAnnotation("Mongo:ElementName", "_id"); - - b.Property("Cancellable") - .HasColumnType("BOOLEAN") - .HasColumnName("cancellable") - .HasAnnotation("Mongo:ElementName", "cancellable"); - - b.Property("Cancelled") - .HasColumnType("BOOLEAN") - .HasColumnName("cancelled") - .HasAnnotation("Mongo:ElementName", "cancelled"); - - b.Property("DocumentId") - .HasColumnType("NUMBER(10)") - .HasColumnName("docid") - .HasAnnotation("Mongo:ElementName", "docid"); - - b.Property("DocumentName") - .HasMaxLength(250) - .HasColumnType("NVARCHAR2(250)") - .HasColumnName("docname") - .HasAnnotation("Mongo:ElementName", "docname"); - - b.Property("DocumentPath") - .HasMaxLength(1024) - .HasColumnType("NVARCHAR2(1024)") - .HasColumnName("docpath") - .HasAnnotation("Mongo:ElementName", "docpath"); - - b.Property("DocumentTemplate") - .HasMaxLength(100) - .HasColumnType("NVARCHAR2(100)") - .HasColumnName("doctemplate") - .HasAnnotation("Mongo:ElementName", "doctemplate"); - - b.Property("DocumentType") - .HasMaxLength(100) - .HasColumnType("NVARCHAR2(100)") - .HasColumnName("doctype") - .HasAnnotation("Mongo:ElementName", "doctype"); - - b.Property("EventArgs") - .HasMaxLength(8000) - .HasColumnType("NCLOB") - .HasColumnName("args") - .HasAnnotation("Mongo:ElementName", "args"); - - b.Property("EventType") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("NVARCHAR2(100)") - .HasColumnName("type") - .HasAnnotation("Mongo:ElementName", "type"); - - b.Property("HandlerId") - .HasColumnType("RAW(16)") - .HasColumnName("handler_id") - .HasAnnotation("Mongo:ElementName", "handler_id"); - - b.Property("HostUsername") - .HasMaxLength(100) - .HasColumnType("NVARCHAR2(100)") - .HasColumnName("host_user") - .HasAnnotation("Mongo:ElementName", "host_user"); - - b.Property("Meta") - .IsRequired() - .HasColumnType("NVARCHAR2(2000)") - .HasColumnName("meta") - .HasAnnotation("Mongo:ElementName", "meta"); - - b.Property("ProjectName") - .HasMaxLength(250) - .HasColumnType("NVARCHAR2(250)") - .HasColumnName("projectname") - .HasAnnotation("Mongo:ElementName", "projectname"); - - b.Property("ProjectNum") - .HasMaxLength(100) - .HasColumnType("NVARCHAR2(100)") - .HasColumnName("projectnum") - .HasAnnotation("Mongo:ElementName", "projectnum"); - - b.Property("RevitBuild") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("NVARCHAR2(100)") - .HasColumnName("revitbuild") - .HasAnnotation("Mongo:ElementName", "revitbuild"); - - b.Property("RevitVersion") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("NVARCHAR2(100)") - .HasColumnName("revit") - .HasAnnotation("Mongo:ElementName", "revit"); - - b.Property("Status") - .HasMaxLength(100) - .HasColumnType("NVARCHAR2(100)") - .HasColumnName("status") - .HasAnnotation("Mongo:ElementName", "status"); - - b.Property("Timestamp") - .HasColumnType("TIMESTAMP(7) WITH TIME ZONE") - .HasColumnName("timestamp") - .HasAnnotation("Mongo:ElementName", "timestamp"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("NVARCHAR2(100)") - .HasColumnName("username") - .HasAnnotation("Mongo:ElementName", "username"); - - b.HasKey("Id"); - - b.ToTable("events", (string)null); - - b.HasAnnotation("Mongo:CollectionName", "events"); - }); - - modelBuilder.Entity("Telemetry.Api.Domain.Models.ScriptRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("RAW(16)") - .HasColumnName("_id") - .HasAnnotation("Mongo:ElementName", "_id"); - - b.Property("CloneName") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("NVARCHAR2(100)") - .HasColumnName("clone") - .HasAnnotation("Mongo:ElementName", "clone"); - - b.Property("CommandBundle") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("NVARCHAR2(250)") - .HasColumnName("commandbundle") - .HasAnnotation("Mongo:ElementName", "commandbundle"); - - b.Property("CommandExtension") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("NVARCHAR2(250)") - .HasColumnName("commandextension") - .HasAnnotation("Mongo:ElementName", "commandextension"); - - b.Property("CommandName") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("NVARCHAR2(250)") - .HasColumnName("commandname") - .HasAnnotation("Mongo:ElementName", "commandname"); - - b.Property("CommandResults") - .HasMaxLength(8000) - .HasColumnType("NCLOB") - .HasColumnName("commandresults") - .HasAnnotation("Mongo:ElementName", "commandresults"); - - b.Property("CommandUniqueName") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("NVARCHAR2(500)") - .HasColumnName("commanduniquename") - .HasAnnotation("Mongo:ElementName", "commanduniquename"); - - b.Property("DocumentName") - .HasMaxLength(250) - .HasColumnType("NVARCHAR2(250)") - .HasColumnName("docname") - .HasAnnotation("Mongo:ElementName", "docname"); - - b.Property("DocumentPath") - .HasMaxLength(1024) - .HasColumnType("NVARCHAR2(1024)") - .HasColumnName("docpath") - .HasAnnotation("Mongo:ElementName", "docpath"); - - b.Property("ExecId") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("NVARCHAR2(100)") - .HasColumnName("exec_id") - .HasAnnotation("Mongo:ElementName", "exec_id"); - - b.Property("ExecTimestamp") - .HasColumnType("TIMESTAMP(7) WITH TIME ZONE") - .HasColumnName("exec_timestamp") - .HasAnnotation("Mongo:ElementName", "exec_timestamp"); - - b.Property("HostUsername") - .HasMaxLength(100) - .HasColumnType("NVARCHAR2(100)") - .HasColumnName("host_user") - .HasAnnotation("Mongo:ElementName", "host_user"); - - b.Property("IsConfig") - .HasColumnType("BOOLEAN") - .HasColumnName("config") - .HasAnnotation("Mongo:ElementName", "config"); - - b.Property("IsDebug") - .HasColumnType("BOOLEAN") - .HasColumnName("debug") - .HasAnnotation("Mongo:ElementName", "debug"); - - b.Property("IsExecFromGui") - .HasColumnType("BOOLEAN") - .HasColumnName("from_gui") - .HasAnnotation("Mongo:ElementName", "from_gui"); - - b.Property("Meta") - .IsRequired() - .HasColumnType("NVARCHAR2(2000)") - .HasColumnName("meta") - .HasAnnotation("Mongo:ElementName", "meta"); - - b.Property("PyRevitVersion") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("NVARCHAR2(100)") - .HasColumnName("pyrevit") - .HasAnnotation("Mongo:ElementName", "pyrevit"); - - b.Property("ResultCode") - .HasColumnType("NUMBER(10)") - .HasColumnName("resultcode") - .HasAnnotation("Mongo:ElementName", "resultcode"); - - b.Property("RevitBuild") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("NVARCHAR2(100)") - .HasColumnName("revitbuild") - .HasAnnotation("Mongo:ElementName", "revitbuild"); - - b.Property("RevitVersion") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("NVARCHAR2(100)") - .HasColumnName("revit") - .HasAnnotation("Mongo:ElementName", "revit"); - - b.Property("ScriptPath") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("NVARCHAR2(1024)") - .HasColumnName("scriptpath") - .HasAnnotation("Mongo:ElementName", "scriptpath"); - - b.Property("SessionId") - .HasColumnType("RAW(16)") - .HasColumnName("sessionid") - .HasAnnotation("Mongo:ElementName", "sessionid"); - - b.Property("Timestamp") - .HasColumnType("TIMESTAMP(7) WITH TIME ZONE") - .HasColumnName("timestamp") - .HasAnnotation("Mongo:ElementName", "timestamp"); - - b.Property("Trace") - .IsRequired() - .HasColumnType("NVARCHAR2(2000)") - .HasColumnName("trace") - .HasAnnotation("Mongo:ElementName", "trace"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("NVARCHAR2(100)") - .HasColumnName("username") - .HasAnnotation("Mongo:ElementName", "username"); - - b.HasKey("Id"); - - b.ToTable("scripts", (string)null); - - b.HasAnnotation("Mongo:CollectionName", "scripts"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Telemetry.Migrations.Oracle/Migrations/20260406101958_UpdateDynamicDataOracle.cs b/src/Telemetry.Migrations.Oracle/Migrations/20260406101958_UpdateDynamicDataOracle.cs deleted file mode 100644 index 8867cc0..0000000 --- a/src/Telemetry.Migrations.Oracle/Migrations/20260406101958_UpdateDynamicDataOracle.cs +++ /dev/null @@ -1,90 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Telemetry.Migrations.Oracle.Migrations -{ - /// - public partial class UpdateDynamicDataOracle : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropPrimaryKey( - name: "PK_script_record", - table: "script_record"); - - migrationBuilder.DropPrimaryKey( - name: "PK_event_record", - table: "event_record"); - - migrationBuilder.RenameTable( - name: "script_record", - newName: "scripts"); - - migrationBuilder.RenameTable( - name: "event_record", - newName: "events"); - - migrationBuilder.RenameColumn( - name: "id", - table: "scripts", - newName: "_id"); - - migrationBuilder.RenameColumn( - name: "id", - table: "events", - newName: "_id"); - - migrationBuilder.AddPrimaryKey( - name: "PK_scripts", - table: "scripts", - column: "_id"); - - migrationBuilder.AddPrimaryKey( - name: "PK_events", - table: "events", - column: "_id"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropPrimaryKey( - name: "PK_scripts", - table: "scripts"); - - migrationBuilder.DropPrimaryKey( - name: "PK_events", - table: "events"); - - migrationBuilder.RenameTable( - name: "scripts", - newName: "script_record"); - - migrationBuilder.RenameTable( - name: "events", - newName: "event_record"); - - migrationBuilder.RenameColumn( - name: "_id", - table: "script_record", - newName: "id"); - - migrationBuilder.RenameColumn( - name: "_id", - table: "event_record", - newName: "id"); - - migrationBuilder.AddPrimaryKey( - name: "PK_script_record", - table: "script_record", - column: "id"); - - migrationBuilder.AddPrimaryKey( - name: "PK_event_record", - table: "event_record", - column: "id"); - } - } -} diff --git a/src/Telemetry.Migrations.Oracle/Migrations/ApplicationDbContextModelSnapshot.cs b/src/Telemetry.Migrations.Oracle/Migrations/ApplicationDbContextModelSnapshot.cs deleted file mode 100644 index af1ac4b..0000000 --- a/src/Telemetry.Migrations.Oracle/Migrations/ApplicationDbContextModelSnapshot.cs +++ /dev/null @@ -1,318 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Oracle.EntityFrameworkCore.Metadata; -using Telemetry.Api.Infrastructure.Persistence; - -#nullable disable - -namespace Telemetry.Migrations.Oracle.Migrations -{ - [DbContext(typeof(ApplicationDbContext))] - partial class ApplicationDbContextModelSnapshot : ModelSnapshot - { - protected override void BuildModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "10.0.5") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - OracleModelBuilderExtensions.UseIdentityColumns(modelBuilder); - - modelBuilder.Entity("Telemetry.Api.Domain.Models.EventRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("RAW(16)") - .HasColumnName("_id") - .HasAnnotation("Mongo:ElementName", "_id"); - - b.Property("Cancellable") - .HasColumnType("BOOLEAN") - .HasColumnName("cancellable") - .HasAnnotation("Mongo:ElementName", "cancellable"); - - b.Property("Cancelled") - .HasColumnType("BOOLEAN") - .HasColumnName("cancelled") - .HasAnnotation("Mongo:ElementName", "cancelled"); - - b.Property("DocumentId") - .HasColumnType("NUMBER(10)") - .HasColumnName("docid") - .HasAnnotation("Mongo:ElementName", "docid"); - - b.Property("DocumentName") - .HasMaxLength(250) - .HasColumnType("NVARCHAR2(250)") - .HasColumnName("docname") - .HasAnnotation("Mongo:ElementName", "docname"); - - b.Property("DocumentPath") - .HasMaxLength(1024) - .HasColumnType("NVARCHAR2(1024)") - .HasColumnName("docpath") - .HasAnnotation("Mongo:ElementName", "docpath"); - - b.Property("DocumentTemplate") - .HasMaxLength(100) - .HasColumnType("NVARCHAR2(100)") - .HasColumnName("doctemplate") - .HasAnnotation("Mongo:ElementName", "doctemplate"); - - b.Property("DocumentType") - .HasMaxLength(100) - .HasColumnType("NVARCHAR2(100)") - .HasColumnName("doctype") - .HasAnnotation("Mongo:ElementName", "doctype"); - - b.Property("EventArgs") - .HasMaxLength(8000) - .HasColumnType("NCLOB") - .HasColumnName("args") - .HasAnnotation("Mongo:ElementName", "args"); - - b.Property("EventType") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("NVARCHAR2(100)") - .HasColumnName("type") - .HasAnnotation("Mongo:ElementName", "type"); - - b.Property("HandlerId") - .HasColumnType("RAW(16)") - .HasColumnName("handler_id") - .HasAnnotation("Mongo:ElementName", "handler_id"); - - b.Property("HostUsername") - .HasMaxLength(100) - .HasColumnType("NVARCHAR2(100)") - .HasColumnName("host_user") - .HasAnnotation("Mongo:ElementName", "host_user"); - - b.Property("Meta") - .IsRequired() - .HasColumnType("NVARCHAR2(2000)") - .HasColumnName("meta") - .HasAnnotation("Mongo:ElementName", "meta"); - - b.Property("ProjectName") - .HasMaxLength(250) - .HasColumnType("NVARCHAR2(250)") - .HasColumnName("projectname") - .HasAnnotation("Mongo:ElementName", "projectname"); - - b.Property("ProjectNum") - .HasMaxLength(100) - .HasColumnType("NVARCHAR2(100)") - .HasColumnName("projectnum") - .HasAnnotation("Mongo:ElementName", "projectnum"); - - b.Property("RevitBuild") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("NVARCHAR2(100)") - .HasColumnName("revitbuild") - .HasAnnotation("Mongo:ElementName", "revitbuild"); - - b.Property("RevitVersion") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("NVARCHAR2(100)") - .HasColumnName("revit") - .HasAnnotation("Mongo:ElementName", "revit"); - - b.Property("Status") - .HasMaxLength(100) - .HasColumnType("NVARCHAR2(100)") - .HasColumnName("status") - .HasAnnotation("Mongo:ElementName", "status"); - - b.Property("Timestamp") - .HasColumnType("TIMESTAMP(7) WITH TIME ZONE") - .HasColumnName("timestamp") - .HasAnnotation("Mongo:ElementName", "timestamp"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("NVARCHAR2(100)") - .HasColumnName("username") - .HasAnnotation("Mongo:ElementName", "username"); - - b.HasKey("Id"); - - b.ToTable("events", (string)null); - - b.HasAnnotation("Mongo:CollectionName", "events"); - }); - - modelBuilder.Entity("Telemetry.Api.Domain.Models.ScriptRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("RAW(16)") - .HasColumnName("_id") - .HasAnnotation("Mongo:ElementName", "_id"); - - b.Property("CloneName") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("NVARCHAR2(100)") - .HasColumnName("clone") - .HasAnnotation("Mongo:ElementName", "clone"); - - b.Property("CommandBundle") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("NVARCHAR2(250)") - .HasColumnName("commandbundle") - .HasAnnotation("Mongo:ElementName", "commandbundle"); - - b.Property("CommandExtension") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("NVARCHAR2(250)") - .HasColumnName("commandextension") - .HasAnnotation("Mongo:ElementName", "commandextension"); - - b.Property("CommandName") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("NVARCHAR2(250)") - .HasColumnName("commandname") - .HasAnnotation("Mongo:ElementName", "commandname"); - - b.Property("CommandResults") - .HasMaxLength(8000) - .HasColumnType("NCLOB") - .HasColumnName("commandresults") - .HasAnnotation("Mongo:ElementName", "commandresults"); - - b.Property("CommandUniqueName") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("NVARCHAR2(500)") - .HasColumnName("commanduniquename") - .HasAnnotation("Mongo:ElementName", "commanduniquename"); - - b.Property("DocumentName") - .HasMaxLength(250) - .HasColumnType("NVARCHAR2(250)") - .HasColumnName("docname") - .HasAnnotation("Mongo:ElementName", "docname"); - - b.Property("DocumentPath") - .HasMaxLength(1024) - .HasColumnType("NVARCHAR2(1024)") - .HasColumnName("docpath") - .HasAnnotation("Mongo:ElementName", "docpath"); - - b.Property("ExecId") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("NVARCHAR2(100)") - .HasColumnName("exec_id") - .HasAnnotation("Mongo:ElementName", "exec_id"); - - b.Property("ExecTimestamp") - .HasColumnType("TIMESTAMP(7) WITH TIME ZONE") - .HasColumnName("exec_timestamp") - .HasAnnotation("Mongo:ElementName", "exec_timestamp"); - - b.Property("HostUsername") - .HasMaxLength(100) - .HasColumnType("NVARCHAR2(100)") - .HasColumnName("host_user") - .HasAnnotation("Mongo:ElementName", "host_user"); - - b.Property("IsConfig") - .HasColumnType("BOOLEAN") - .HasColumnName("config") - .HasAnnotation("Mongo:ElementName", "config"); - - b.Property("IsDebug") - .HasColumnType("BOOLEAN") - .HasColumnName("debug") - .HasAnnotation("Mongo:ElementName", "debug"); - - b.Property("IsExecFromGui") - .HasColumnType("BOOLEAN") - .HasColumnName("from_gui") - .HasAnnotation("Mongo:ElementName", "from_gui"); - - b.Property("Meta") - .IsRequired() - .HasColumnType("NVARCHAR2(2000)") - .HasColumnName("meta") - .HasAnnotation("Mongo:ElementName", "meta"); - - b.Property("PyRevitVersion") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("NVARCHAR2(100)") - .HasColumnName("pyrevit") - .HasAnnotation("Mongo:ElementName", "pyrevit"); - - b.Property("ResultCode") - .HasColumnType("NUMBER(10)") - .HasColumnName("resultcode") - .HasAnnotation("Mongo:ElementName", "resultcode"); - - b.Property("RevitBuild") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("NVARCHAR2(100)") - .HasColumnName("revitbuild") - .HasAnnotation("Mongo:ElementName", "revitbuild"); - - b.Property("RevitVersion") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("NVARCHAR2(100)") - .HasColumnName("revit") - .HasAnnotation("Mongo:ElementName", "revit"); - - b.Property("ScriptPath") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("NVARCHAR2(1024)") - .HasColumnName("scriptpath") - .HasAnnotation("Mongo:ElementName", "scriptpath"); - - b.Property("SessionId") - .HasColumnType("RAW(16)") - .HasColumnName("sessionid") - .HasAnnotation("Mongo:ElementName", "sessionid"); - - b.Property("Timestamp") - .HasColumnType("TIMESTAMP(7) WITH TIME ZONE") - .HasColumnName("timestamp") - .HasAnnotation("Mongo:ElementName", "timestamp"); - - b.Property("Trace") - .IsRequired() - .HasColumnType("NVARCHAR2(2000)") - .HasColumnName("trace") - .HasAnnotation("Mongo:ElementName", "trace"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("NVARCHAR2(100)") - .HasColumnName("username") - .HasAnnotation("Mongo:ElementName", "username"); - - b.HasKey("Id"); - - b.ToTable("scripts", (string)null); - - b.HasAnnotation("Mongo:CollectionName", "scripts"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Telemetry.Migrations.Postgres/Migrations/20260330090711_InitPostgres.Designer.cs b/src/Telemetry.Migrations.Postgres/Migrations/20260330090711_InitPostgres.Designer.cs deleted file mode 100644 index a2baa5d..0000000 --- a/src/Telemetry.Migrations.Postgres/Migrations/20260330090711_InitPostgres.Designer.cs +++ /dev/null @@ -1,271 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -using Telemetry.Api.Infrastructure.Persistence; - -#nullable disable - -namespace Telemetry.Migrations.Postgres.Migrations -{ - [DbContext(typeof(ApplicationDbContext))] - [Migration("20260330090711_InitPostgres")] - partial class InitPostgres - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "10.0.5") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("Telemetry.Api.Domain.Models.EventRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid") - .HasColumnName("id"); - - b.Property("Cancellable") - .HasColumnType("boolean"); - - b.Property("Cancelled") - .HasColumnType("boolean") - .HasColumnName("cancelled"); - - b.Property("DocumentId") - .HasColumnType("integer") - .HasColumnName("docid"); - - b.Property("DocumentName") - .HasMaxLength(250) - .HasColumnType("character varying(250)") - .HasColumnName("docname"); - - b.Property("DocumentPath") - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasColumnName("docpath"); - - b.Property("DocumentTemplate") - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("doctemplate"); - - b.Property("DocumentType") - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("doctype"); - - b.Property("EventArgs") - .HasMaxLength(8000) - .HasColumnType("character varying(8000)") - .HasColumnName("args"); - - b.Property("EventType") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("type"); - - b.Property("HandlerId") - .HasColumnType("uuid") - .HasColumnName("handler_id"); - - b.Property("HostUsername") - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("host_user"); - - b.Property("Meta") - .IsRequired() - .HasColumnType("text") - .HasColumnName("meta"); - - b.Property("ProjectName") - .HasMaxLength(250) - .HasColumnType("character varying(250)") - .HasColumnName("projectname"); - - b.Property("ProjectNum") - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("projectnum"); - - b.Property("RevitBuild") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("revitbuild"); - - b.Property("RevitVersion") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("revit"); - - b.Property("Status") - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("status"); - - b.Property("Timestamp") - .HasColumnType("timestamp with time zone") - .HasColumnName("timestamp"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("username"); - - b.HasKey("Id"); - - b.ToTable("event_record", (string)null); - }); - - modelBuilder.Entity("Telemetry.Api.Domain.Models.ScriptRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid") - .HasColumnName("id"); - - b.Property("CloneName") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("clone"); - - b.Property("CommandBundle") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("character varying(250)") - .HasColumnName("commandbundle"); - - b.Property("CommandExtension") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("character varying(250)") - .HasColumnName("commandextension"); - - b.Property("CommandName") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("character varying(250)") - .HasColumnName("commandname"); - - b.Property("CommandResults") - .HasMaxLength(8000) - .HasColumnType("character varying(8000)") - .HasColumnName("commandresults"); - - b.Property("CommandUniqueName") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("character varying(500)") - .HasColumnName("commanduniquename"); - - b.Property("DocumentName") - .HasMaxLength(250) - .HasColumnType("character varying(250)") - .HasColumnName("docname"); - - b.Property("DocumentPath") - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasColumnName("docpath"); - - b.Property("ExecId") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("exec_id"); - - b.Property("ExecTimestamp") - .HasColumnType("timestamp with time zone") - .HasColumnName("exec_timestamp"); - - b.Property("HostUsername") - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("host_user"); - - b.Property("IsConfig") - .HasColumnType("boolean") - .HasColumnName("config"); - - b.Property("IsDebug") - .HasColumnType("boolean") - .HasColumnName("debug"); - - b.Property("IsExecFromGui") - .HasColumnType("boolean") - .HasColumnName("from_gui"); - - b.Property("Meta") - .IsRequired() - .HasColumnType("text") - .HasColumnName("meta"); - - b.Property("PyRevitVersion") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("pyrevit"); - - b.Property("ResultCode") - .HasColumnType("integer") - .HasColumnName("resultcode"); - - b.Property("RevitBuild") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("revitbuild"); - - b.Property("RevitVersion") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("revit"); - - b.Property("ScriptPath") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasColumnName("scriptpath"); - - b.Property("SessionId") - .HasColumnType("uuid") - .HasColumnName("sessionid"); - - b.Property("Timestamp") - .HasColumnType("timestamp with time zone") - .HasColumnName("timestamp"); - - b.Property("Trace") - .IsRequired() - .HasColumnType("text") - .HasColumnName("trace"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("username"); - - b.HasKey("Id"); - - b.ToTable("script_record", (string)null); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Telemetry.Migrations.Postgres/Migrations/20260330090711_InitPostgres.cs b/src/Telemetry.Migrations.Postgres/Migrations/20260330090711_InitPostgres.cs deleted file mode 100644 index 2755cc2..0000000 --- a/src/Telemetry.Migrations.Postgres/Migrations/20260330090711_InitPostgres.cs +++ /dev/null @@ -1,90 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Telemetry.Migrations.Postgres.Migrations -{ - /// - public partial class InitPostgres : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "event_record", - columns: table => new - { - id = table.Column(type: "uuid", nullable: false), - handler_id = table.Column(type: "uuid", nullable: false), - meta = table.Column(type: "text", nullable: false), - type = table.Column(type: "character varying(100)", maxLength: 100, nullable: false), - status = table.Column(type: "character varying(100)", maxLength: 100, nullable: true), - timestamp = table.Column(type: "timestamp with time zone", nullable: false), - username = table.Column(type: "character varying(100)", maxLength: 100, nullable: false), - host_user = table.Column(type: "character varying(100)", maxLength: 100, nullable: true), - revitbuild = table.Column(type: "character varying(100)", maxLength: 100, nullable: false), - revit = table.Column(type: "character varying(100)", maxLength: 100, nullable: false), - cancelled = table.Column(type: "boolean", nullable: true), - Cancellable = table.Column(type: "boolean", nullable: true), - docid = table.Column(type: "integer", nullable: false), - doctype = table.Column(type: "character varying(100)", maxLength: 100, nullable: true), - doctemplate = table.Column(type: "character varying(100)", maxLength: 100, nullable: true), - docname = table.Column(type: "character varying(250)", maxLength: 250, nullable: true), - docpath = table.Column(type: "character varying(1024)", maxLength: 1024, nullable: true), - projectname = table.Column(type: "character varying(250)", maxLength: 250, nullable: true), - projectnum = table.Column(type: "character varying(100)", maxLength: 100, nullable: true), - args = table.Column(type: "character varying(8000)", maxLength: 8000, nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_event_record", x => x.id); - }); - - migrationBuilder.CreateTable( - name: "script_record", - columns: table => new - { - id = table.Column(type: "uuid", nullable: false), - sessionid = table.Column(type: "uuid", nullable: false), - meta = table.Column(type: "text", nullable: false), - timestamp = table.Column(type: "timestamp with time zone", nullable: false), - username = table.Column(type: "character varying(100)", maxLength: 100, nullable: false), - host_user = table.Column(type: "character varying(100)", maxLength: 100, nullable: true), - revitbuild = table.Column(type: "character varying(100)", maxLength: 100, nullable: false), - revit = table.Column(type: "character varying(100)", maxLength: 100, nullable: false), - pyrevit = table.Column(type: "character varying(100)", maxLength: 100, nullable: false), - clone = table.Column(type: "character varying(100)", maxLength: 100, nullable: false), - debug = table.Column(type: "boolean", nullable: false), - config = table.Column(type: "boolean", nullable: false), - from_gui = table.Column(type: "boolean", nullable: false), - exec_id = table.Column(type: "character varying(100)", maxLength: 100, nullable: false), - exec_timestamp = table.Column(type: "timestamp with time zone", nullable: false), - commandbundle = table.Column(type: "character varying(250)", maxLength: 250, nullable: false), - commandextension = table.Column(type: "character varying(250)", maxLength: 250, nullable: false), - commandname = table.Column(type: "character varying(250)", maxLength: 250, nullable: false), - commanduniquename = table.Column(type: "character varying(500)", maxLength: 500, nullable: false), - docname = table.Column(type: "character varying(250)", maxLength: 250, nullable: true), - docpath = table.Column(type: "character varying(1024)", maxLength: 1024, nullable: true), - resultcode = table.Column(type: "integer", nullable: false), - scriptpath = table.Column(type: "character varying(1024)", maxLength: 1024, nullable: false), - trace = table.Column(type: "text", nullable: false), - commandresults = table.Column(type: "character varying(8000)", maxLength: 8000, nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_script_record", x => x.id); - }); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "event_record"); - - migrationBuilder.DropTable( - name: "script_record"); - } - } -} diff --git a/src/Telemetry.Migrations.Postgres/Migrations/20260402141612_AddCancellablePostgres.Designer.cs b/src/Telemetry.Migrations.Postgres/Migrations/20260402141612_AddCancellablePostgres.Designer.cs deleted file mode 100644 index 7fb51e5..0000000 --- a/src/Telemetry.Migrations.Postgres/Migrations/20260402141612_AddCancellablePostgres.Designer.cs +++ /dev/null @@ -1,272 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -using Telemetry.Api.Infrastructure.Persistence; - -#nullable disable - -namespace Telemetry.Migrations.Postgres.Migrations -{ - [DbContext(typeof(ApplicationDbContext))] - [Migration("20260402141612_AddCancellablePostgres")] - partial class AddCancellablePostgres - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "10.0.5") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("Telemetry.Api.Domain.Models.EventRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid") - .HasColumnName("id"); - - b.Property("Cancellable") - .HasColumnType("boolean") - .HasColumnName("cancellable"); - - b.Property("Cancelled") - .HasColumnType("boolean") - .HasColumnName("cancelled"); - - b.Property("DocumentId") - .HasColumnType("integer") - .HasColumnName("docid"); - - b.Property("DocumentName") - .HasMaxLength(250) - .HasColumnType("character varying(250)") - .HasColumnName("docname"); - - b.Property("DocumentPath") - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasColumnName("docpath"); - - b.Property("DocumentTemplate") - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("doctemplate"); - - b.Property("DocumentType") - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("doctype"); - - b.Property("EventArgs") - .HasMaxLength(8000) - .HasColumnType("character varying(8000)") - .HasColumnName("args"); - - b.Property("EventType") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("type"); - - b.Property("HandlerId") - .HasColumnType("uuid") - .HasColumnName("handler_id"); - - b.Property("HostUsername") - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("host_user"); - - b.Property("Meta") - .IsRequired() - .HasColumnType("text") - .HasColumnName("meta"); - - b.Property("ProjectName") - .HasMaxLength(250) - .HasColumnType("character varying(250)") - .HasColumnName("projectname"); - - b.Property("ProjectNum") - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("projectnum"); - - b.Property("RevitBuild") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("revitbuild"); - - b.Property("RevitVersion") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("revit"); - - b.Property("Status") - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("status"); - - b.Property("Timestamp") - .HasColumnType("timestamp with time zone") - .HasColumnName("timestamp"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("username"); - - b.HasKey("Id"); - - b.ToTable("event_record", (string)null); - }); - - modelBuilder.Entity("Telemetry.Api.Domain.Models.ScriptRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid") - .HasColumnName("id"); - - b.Property("CloneName") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("clone"); - - b.Property("CommandBundle") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("character varying(250)") - .HasColumnName("commandbundle"); - - b.Property("CommandExtension") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("character varying(250)") - .HasColumnName("commandextension"); - - b.Property("CommandName") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("character varying(250)") - .HasColumnName("commandname"); - - b.Property("CommandResults") - .HasMaxLength(8000) - .HasColumnType("character varying(8000)") - .HasColumnName("commandresults"); - - b.Property("CommandUniqueName") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("character varying(500)") - .HasColumnName("commanduniquename"); - - b.Property("DocumentName") - .HasMaxLength(250) - .HasColumnType("character varying(250)") - .HasColumnName("docname"); - - b.Property("DocumentPath") - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasColumnName("docpath"); - - b.Property("ExecId") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("exec_id"); - - b.Property("ExecTimestamp") - .HasColumnType("timestamp with time zone") - .HasColumnName("exec_timestamp"); - - b.Property("HostUsername") - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("host_user"); - - b.Property("IsConfig") - .HasColumnType("boolean") - .HasColumnName("config"); - - b.Property("IsDebug") - .HasColumnType("boolean") - .HasColumnName("debug"); - - b.Property("IsExecFromGui") - .HasColumnType("boolean") - .HasColumnName("from_gui"); - - b.Property("Meta") - .IsRequired() - .HasColumnType("text") - .HasColumnName("meta"); - - b.Property("PyRevitVersion") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("pyrevit"); - - b.Property("ResultCode") - .HasColumnType("integer") - .HasColumnName("resultcode"); - - b.Property("RevitBuild") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("revitbuild"); - - b.Property("RevitVersion") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("revit"); - - b.Property("ScriptPath") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasColumnName("scriptpath"); - - b.Property("SessionId") - .HasColumnType("uuid") - .HasColumnName("sessionid"); - - b.Property("Timestamp") - .HasColumnType("timestamp with time zone") - .HasColumnName("timestamp"); - - b.Property("Trace") - .IsRequired() - .HasColumnType("text") - .HasColumnName("trace"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("username"); - - b.HasKey("Id"); - - b.ToTable("script_record", (string)null); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Telemetry.Migrations.Postgres/Migrations/20260402141612_AddCancellablePostgres.cs b/src/Telemetry.Migrations.Postgres/Migrations/20260402141612_AddCancellablePostgres.cs deleted file mode 100644 index 5258089..0000000 --- a/src/Telemetry.Migrations.Postgres/Migrations/20260402141612_AddCancellablePostgres.cs +++ /dev/null @@ -1,28 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Telemetry.Migrations.Postgres.Migrations -{ - /// - public partial class AddCancellablePostgres : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.RenameColumn( - name: "Cancellable", - table: "event_record", - newName: "cancellable"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.RenameColumn( - name: "cancellable", - table: "event_record", - newName: "Cancellable"); - } - } -} diff --git a/src/Telemetry.Migrations.Postgres/Migrations/20260406102030_UpdateDynamicDataPostgres.Designer.cs b/src/Telemetry.Migrations.Postgres/Migrations/20260406102030_UpdateDynamicDataPostgres.Designer.cs deleted file mode 100644 index 3689a96..0000000 --- a/src/Telemetry.Migrations.Postgres/Migrations/20260406102030_UpdateDynamicDataPostgres.Designer.cs +++ /dev/null @@ -1,321 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -using Telemetry.Api.Infrastructure.Persistence; - -#nullable disable - -namespace Telemetry.Migrations.Postgres.Migrations -{ - [DbContext(typeof(ApplicationDbContext))] - [Migration("20260406102030_UpdateDynamicDataPostgres")] - partial class UpdateDynamicDataPostgres - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "10.0.5") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("Telemetry.Api.Domain.Models.EventRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid") - .HasColumnName("_id") - .HasAnnotation("Mongo:ElementName", "_id"); - - b.Property("Cancellable") - .HasColumnType("boolean") - .HasColumnName("cancellable") - .HasAnnotation("Mongo:ElementName", "cancellable"); - - b.Property("Cancelled") - .HasColumnType("boolean") - .HasColumnName("cancelled") - .HasAnnotation("Mongo:ElementName", "cancelled"); - - b.Property("DocumentId") - .HasColumnType("integer") - .HasColumnName("docid") - .HasAnnotation("Mongo:ElementName", "docid"); - - b.Property("DocumentName") - .HasMaxLength(250) - .HasColumnType("character varying(250)") - .HasColumnName("docname") - .HasAnnotation("Mongo:ElementName", "docname"); - - b.Property("DocumentPath") - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasColumnName("docpath") - .HasAnnotation("Mongo:ElementName", "docpath"); - - b.Property("DocumentTemplate") - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("doctemplate") - .HasAnnotation("Mongo:ElementName", "doctemplate"); - - b.Property("DocumentType") - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("doctype") - .HasAnnotation("Mongo:ElementName", "doctype"); - - b.Property("EventArgs") - .HasMaxLength(8000) - .HasColumnType("character varying(8000)") - .HasColumnName("args") - .HasAnnotation("Mongo:ElementName", "args"); - - b.Property("EventType") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("type") - .HasAnnotation("Mongo:ElementName", "type"); - - b.Property("HandlerId") - .HasColumnType("uuid") - .HasColumnName("handler_id") - .HasAnnotation("Mongo:ElementName", "handler_id"); - - b.Property("HostUsername") - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("host_user") - .HasAnnotation("Mongo:ElementName", "host_user"); - - b.Property("Meta") - .IsRequired() - .HasColumnType("text") - .HasColumnName("meta") - .HasAnnotation("Mongo:ElementName", "meta"); - - b.Property("ProjectName") - .HasMaxLength(250) - .HasColumnType("character varying(250)") - .HasColumnName("projectname") - .HasAnnotation("Mongo:ElementName", "projectname"); - - b.Property("ProjectNum") - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("projectnum") - .HasAnnotation("Mongo:ElementName", "projectnum"); - - b.Property("RevitBuild") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("revitbuild") - .HasAnnotation("Mongo:ElementName", "revitbuild"); - - b.Property("RevitVersion") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("revit") - .HasAnnotation("Mongo:ElementName", "revit"); - - b.Property("Status") - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("status") - .HasAnnotation("Mongo:ElementName", "status"); - - b.Property("Timestamp") - .HasColumnType("timestamp with time zone") - .HasColumnName("timestamp") - .HasAnnotation("Mongo:ElementName", "timestamp"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("username") - .HasAnnotation("Mongo:ElementName", "username"); - - b.HasKey("Id"); - - b.ToTable("events", (string)null); - - b.HasAnnotation("Mongo:CollectionName", "events"); - }); - - modelBuilder.Entity("Telemetry.Api.Domain.Models.ScriptRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid") - .HasColumnName("_id") - .HasAnnotation("Mongo:ElementName", "_id"); - - b.Property("CloneName") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("clone") - .HasAnnotation("Mongo:ElementName", "clone"); - - b.Property("CommandBundle") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("character varying(250)") - .HasColumnName("commandbundle") - .HasAnnotation("Mongo:ElementName", "commandbundle"); - - b.Property("CommandExtension") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("character varying(250)") - .HasColumnName("commandextension") - .HasAnnotation("Mongo:ElementName", "commandextension"); - - b.Property("CommandName") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("character varying(250)") - .HasColumnName("commandname") - .HasAnnotation("Mongo:ElementName", "commandname"); - - b.Property("CommandResults") - .HasMaxLength(8000) - .HasColumnType("character varying(8000)") - .HasColumnName("commandresults") - .HasAnnotation("Mongo:ElementName", "commandresults"); - - b.Property("CommandUniqueName") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("character varying(500)") - .HasColumnName("commanduniquename") - .HasAnnotation("Mongo:ElementName", "commanduniquename"); - - b.Property("DocumentName") - .HasMaxLength(250) - .HasColumnType("character varying(250)") - .HasColumnName("docname") - .HasAnnotation("Mongo:ElementName", "docname"); - - b.Property("DocumentPath") - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasColumnName("docpath") - .HasAnnotation("Mongo:ElementName", "docpath"); - - b.Property("ExecId") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("exec_id") - .HasAnnotation("Mongo:ElementName", "exec_id"); - - b.Property("ExecTimestamp") - .HasColumnType("timestamp with time zone") - .HasColumnName("exec_timestamp") - .HasAnnotation("Mongo:ElementName", "exec_timestamp"); - - b.Property("HostUsername") - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("host_user") - .HasAnnotation("Mongo:ElementName", "host_user"); - - b.Property("IsConfig") - .HasColumnType("boolean") - .HasColumnName("config") - .HasAnnotation("Mongo:ElementName", "config"); - - b.Property("IsDebug") - .HasColumnType("boolean") - .HasColumnName("debug") - .HasAnnotation("Mongo:ElementName", "debug"); - - b.Property("IsExecFromGui") - .HasColumnType("boolean") - .HasColumnName("from_gui") - .HasAnnotation("Mongo:ElementName", "from_gui"); - - b.Property("Meta") - .IsRequired() - .HasColumnType("text") - .HasColumnName("meta") - .HasAnnotation("Mongo:ElementName", "meta"); - - b.Property("PyRevitVersion") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("pyrevit") - .HasAnnotation("Mongo:ElementName", "pyrevit"); - - b.Property("ResultCode") - .HasColumnType("integer") - .HasColumnName("resultcode") - .HasAnnotation("Mongo:ElementName", "resultcode"); - - b.Property("RevitBuild") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("revitbuild") - .HasAnnotation("Mongo:ElementName", "revitbuild"); - - b.Property("RevitVersion") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("revit") - .HasAnnotation("Mongo:ElementName", "revit"); - - b.Property("ScriptPath") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasColumnName("scriptpath") - .HasAnnotation("Mongo:ElementName", "scriptpath"); - - b.Property("SessionId") - .HasColumnType("uuid") - .HasColumnName("sessionid") - .HasAnnotation("Mongo:ElementName", "sessionid"); - - b.Property("Timestamp") - .HasColumnType("timestamp with time zone") - .HasColumnName("timestamp") - .HasAnnotation("Mongo:ElementName", "timestamp"); - - b.Property("Trace") - .IsRequired() - .HasColumnType("text") - .HasColumnName("trace") - .HasAnnotation("Mongo:ElementName", "trace"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("username") - .HasAnnotation("Mongo:ElementName", "username"); - - b.HasKey("Id"); - - b.ToTable("scripts", (string)null); - - b.HasAnnotation("Mongo:CollectionName", "scripts"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Telemetry.Migrations.Postgres/Migrations/20260406102030_UpdateDynamicDataPostgres.cs b/src/Telemetry.Migrations.Postgres/Migrations/20260406102030_UpdateDynamicDataPostgres.cs deleted file mode 100644 index 420ea71..0000000 --- a/src/Telemetry.Migrations.Postgres/Migrations/20260406102030_UpdateDynamicDataPostgres.cs +++ /dev/null @@ -1,90 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Telemetry.Migrations.Postgres.Migrations -{ - /// - public partial class UpdateDynamicDataPostgres : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropPrimaryKey( - name: "PK_script_record", - table: "script_record"); - - migrationBuilder.DropPrimaryKey( - name: "PK_event_record", - table: "event_record"); - - migrationBuilder.RenameTable( - name: "script_record", - newName: "scripts"); - - migrationBuilder.RenameTable( - name: "event_record", - newName: "events"); - - migrationBuilder.RenameColumn( - name: "id", - table: "scripts", - newName: "_id"); - - migrationBuilder.RenameColumn( - name: "id", - table: "events", - newName: "_id"); - - migrationBuilder.AddPrimaryKey( - name: "PK_scripts", - table: "scripts", - column: "_id"); - - migrationBuilder.AddPrimaryKey( - name: "PK_events", - table: "events", - column: "_id"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropPrimaryKey( - name: "PK_scripts", - table: "scripts"); - - migrationBuilder.DropPrimaryKey( - name: "PK_events", - table: "events"); - - migrationBuilder.RenameTable( - name: "scripts", - newName: "script_record"); - - migrationBuilder.RenameTable( - name: "events", - newName: "event_record"); - - migrationBuilder.RenameColumn( - name: "_id", - table: "script_record", - newName: "id"); - - migrationBuilder.RenameColumn( - name: "_id", - table: "event_record", - newName: "id"); - - migrationBuilder.AddPrimaryKey( - name: "PK_script_record", - table: "script_record", - column: "id"); - - migrationBuilder.AddPrimaryKey( - name: "PK_event_record", - table: "event_record", - column: "id"); - } - } -} diff --git a/src/Telemetry.Migrations.Postgres/Migrations/ApplicationDbContextModelSnapshot.cs b/src/Telemetry.Migrations.Postgres/Migrations/ApplicationDbContextModelSnapshot.cs deleted file mode 100644 index d18a3cb..0000000 --- a/src/Telemetry.Migrations.Postgres/Migrations/ApplicationDbContextModelSnapshot.cs +++ /dev/null @@ -1,318 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -using Telemetry.Api.Infrastructure.Persistence; - -#nullable disable - -namespace Telemetry.Migrations.Postgres.Migrations -{ - [DbContext(typeof(ApplicationDbContext))] - partial class ApplicationDbContextModelSnapshot : ModelSnapshot - { - protected override void BuildModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "10.0.5") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("Telemetry.Api.Domain.Models.EventRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid") - .HasColumnName("_id") - .HasAnnotation("Mongo:ElementName", "_id"); - - b.Property("Cancellable") - .HasColumnType("boolean") - .HasColumnName("cancellable") - .HasAnnotation("Mongo:ElementName", "cancellable"); - - b.Property("Cancelled") - .HasColumnType("boolean") - .HasColumnName("cancelled") - .HasAnnotation("Mongo:ElementName", "cancelled"); - - b.Property("DocumentId") - .HasColumnType("integer") - .HasColumnName("docid") - .HasAnnotation("Mongo:ElementName", "docid"); - - b.Property("DocumentName") - .HasMaxLength(250) - .HasColumnType("character varying(250)") - .HasColumnName("docname") - .HasAnnotation("Mongo:ElementName", "docname"); - - b.Property("DocumentPath") - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasColumnName("docpath") - .HasAnnotation("Mongo:ElementName", "docpath"); - - b.Property("DocumentTemplate") - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("doctemplate") - .HasAnnotation("Mongo:ElementName", "doctemplate"); - - b.Property("DocumentType") - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("doctype") - .HasAnnotation("Mongo:ElementName", "doctype"); - - b.Property("EventArgs") - .HasMaxLength(8000) - .HasColumnType("character varying(8000)") - .HasColumnName("args") - .HasAnnotation("Mongo:ElementName", "args"); - - b.Property("EventType") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("type") - .HasAnnotation("Mongo:ElementName", "type"); - - b.Property("HandlerId") - .HasColumnType("uuid") - .HasColumnName("handler_id") - .HasAnnotation("Mongo:ElementName", "handler_id"); - - b.Property("HostUsername") - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("host_user") - .HasAnnotation("Mongo:ElementName", "host_user"); - - b.Property("Meta") - .IsRequired() - .HasColumnType("text") - .HasColumnName("meta") - .HasAnnotation("Mongo:ElementName", "meta"); - - b.Property("ProjectName") - .HasMaxLength(250) - .HasColumnType("character varying(250)") - .HasColumnName("projectname") - .HasAnnotation("Mongo:ElementName", "projectname"); - - b.Property("ProjectNum") - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("projectnum") - .HasAnnotation("Mongo:ElementName", "projectnum"); - - b.Property("RevitBuild") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("revitbuild") - .HasAnnotation("Mongo:ElementName", "revitbuild"); - - b.Property("RevitVersion") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("revit") - .HasAnnotation("Mongo:ElementName", "revit"); - - b.Property("Status") - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("status") - .HasAnnotation("Mongo:ElementName", "status"); - - b.Property("Timestamp") - .HasColumnType("timestamp with time zone") - .HasColumnName("timestamp") - .HasAnnotation("Mongo:ElementName", "timestamp"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("username") - .HasAnnotation("Mongo:ElementName", "username"); - - b.HasKey("Id"); - - b.ToTable("events", (string)null); - - b.HasAnnotation("Mongo:CollectionName", "events"); - }); - - modelBuilder.Entity("Telemetry.Api.Domain.Models.ScriptRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid") - .HasColumnName("_id") - .HasAnnotation("Mongo:ElementName", "_id"); - - b.Property("CloneName") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("clone") - .HasAnnotation("Mongo:ElementName", "clone"); - - b.Property("CommandBundle") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("character varying(250)") - .HasColumnName("commandbundle") - .HasAnnotation("Mongo:ElementName", "commandbundle"); - - b.Property("CommandExtension") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("character varying(250)") - .HasColumnName("commandextension") - .HasAnnotation("Mongo:ElementName", "commandextension"); - - b.Property("CommandName") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("character varying(250)") - .HasColumnName("commandname") - .HasAnnotation("Mongo:ElementName", "commandname"); - - b.Property("CommandResults") - .HasMaxLength(8000) - .HasColumnType("character varying(8000)") - .HasColumnName("commandresults") - .HasAnnotation("Mongo:ElementName", "commandresults"); - - b.Property("CommandUniqueName") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("character varying(500)") - .HasColumnName("commanduniquename") - .HasAnnotation("Mongo:ElementName", "commanduniquename"); - - b.Property("DocumentName") - .HasMaxLength(250) - .HasColumnType("character varying(250)") - .HasColumnName("docname") - .HasAnnotation("Mongo:ElementName", "docname"); - - b.Property("DocumentPath") - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasColumnName("docpath") - .HasAnnotation("Mongo:ElementName", "docpath"); - - b.Property("ExecId") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("exec_id") - .HasAnnotation("Mongo:ElementName", "exec_id"); - - b.Property("ExecTimestamp") - .HasColumnType("timestamp with time zone") - .HasColumnName("exec_timestamp") - .HasAnnotation("Mongo:ElementName", "exec_timestamp"); - - b.Property("HostUsername") - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("host_user") - .HasAnnotation("Mongo:ElementName", "host_user"); - - b.Property("IsConfig") - .HasColumnType("boolean") - .HasColumnName("config") - .HasAnnotation("Mongo:ElementName", "config"); - - b.Property("IsDebug") - .HasColumnType("boolean") - .HasColumnName("debug") - .HasAnnotation("Mongo:ElementName", "debug"); - - b.Property("IsExecFromGui") - .HasColumnType("boolean") - .HasColumnName("from_gui") - .HasAnnotation("Mongo:ElementName", "from_gui"); - - b.Property("Meta") - .IsRequired() - .HasColumnType("text") - .HasColumnName("meta") - .HasAnnotation("Mongo:ElementName", "meta"); - - b.Property("PyRevitVersion") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("pyrevit") - .HasAnnotation("Mongo:ElementName", "pyrevit"); - - b.Property("ResultCode") - .HasColumnType("integer") - .HasColumnName("resultcode") - .HasAnnotation("Mongo:ElementName", "resultcode"); - - b.Property("RevitBuild") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("revitbuild") - .HasAnnotation("Mongo:ElementName", "revitbuild"); - - b.Property("RevitVersion") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("revit") - .HasAnnotation("Mongo:ElementName", "revit"); - - b.Property("ScriptPath") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasColumnName("scriptpath") - .HasAnnotation("Mongo:ElementName", "scriptpath"); - - b.Property("SessionId") - .HasColumnType("uuid") - .HasColumnName("sessionid") - .HasAnnotation("Mongo:ElementName", "sessionid"); - - b.Property("Timestamp") - .HasColumnType("timestamp with time zone") - .HasColumnName("timestamp") - .HasAnnotation("Mongo:ElementName", "timestamp"); - - b.Property("Trace") - .IsRequired() - .HasColumnType("text") - .HasColumnName("trace") - .HasAnnotation("Mongo:ElementName", "trace"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("username") - .HasAnnotation("Mongo:ElementName", "username"); - - b.HasKey("Id"); - - b.ToTable("scripts", (string)null); - - b.HasAnnotation("Mongo:CollectionName", "scripts"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Telemetry.Migrations.SqlServer/Migrations/20260330090733_InitSqlServer.Designer.cs b/src/Telemetry.Migrations.SqlServer/Migrations/20260330090733_InitSqlServer.Designer.cs deleted file mode 100644 index 28e8881..0000000 --- a/src/Telemetry.Migrations.SqlServer/Migrations/20260330090733_InitSqlServer.Designer.cs +++ /dev/null @@ -1,271 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Telemetry.Api.Infrastructure.Persistence; - -#nullable disable - -namespace Telemetry.Migrations.SqlServer.Migrations -{ - [DbContext(typeof(ApplicationDbContext))] - [Migration("20260330090733_InitSqlServer")] - partial class InitSqlServer - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "10.0.5") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - - modelBuilder.Entity("Telemetry.Api.Domain.Models.EventRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier") - .HasColumnName("id"); - - b.Property("Cancellable") - .HasColumnType("bit"); - - b.Property("Cancelled") - .HasColumnType("bit") - .HasColumnName("cancelled"); - - b.Property("DocumentId") - .HasColumnType("int") - .HasColumnName("docid"); - - b.Property("DocumentName") - .HasMaxLength(250) - .HasColumnType("nvarchar(250)") - .HasColumnName("docname"); - - b.Property("DocumentPath") - .HasMaxLength(1024) - .HasColumnType("nvarchar(1024)") - .HasColumnName("docpath"); - - b.Property("DocumentTemplate") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasColumnName("doctemplate"); - - b.Property("DocumentType") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasColumnName("doctype"); - - b.Property("EventArgs") - .HasMaxLength(8000) - .HasColumnType("nvarchar(max)") - .HasColumnName("args"); - - b.Property("EventType") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasColumnName("type"); - - b.Property("HandlerId") - .HasColumnType("uniqueidentifier") - .HasColumnName("handler_id"); - - b.Property("HostUsername") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasColumnName("host_user"); - - b.Property("Meta") - .IsRequired() - .HasColumnType("nvarchar(max)") - .HasColumnName("meta"); - - b.Property("ProjectName") - .HasMaxLength(250) - .HasColumnType("nvarchar(250)") - .HasColumnName("projectname"); - - b.Property("ProjectNum") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasColumnName("projectnum"); - - b.Property("RevitBuild") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasColumnName("revitbuild"); - - b.Property("RevitVersion") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasColumnName("revit"); - - b.Property("Status") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasColumnName("status"); - - b.Property("Timestamp") - .HasColumnType("datetimeoffset") - .HasColumnName("timestamp"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasColumnName("username"); - - b.HasKey("Id"); - - b.ToTable("event_record", (string)null); - }); - - modelBuilder.Entity("Telemetry.Api.Domain.Models.ScriptRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier") - .HasColumnName("id"); - - b.Property("CloneName") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasColumnName("clone"); - - b.Property("CommandBundle") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("nvarchar(250)") - .HasColumnName("commandbundle"); - - b.Property("CommandExtension") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("nvarchar(250)") - .HasColumnName("commandextension"); - - b.Property("CommandName") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("nvarchar(250)") - .HasColumnName("commandname"); - - b.Property("CommandResults") - .HasMaxLength(8000) - .HasColumnType("nvarchar(max)") - .HasColumnName("commandresults"); - - b.Property("CommandUniqueName") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("nvarchar(500)") - .HasColumnName("commanduniquename"); - - b.Property("DocumentName") - .HasMaxLength(250) - .HasColumnType("nvarchar(250)") - .HasColumnName("docname"); - - b.Property("DocumentPath") - .HasMaxLength(1024) - .HasColumnType("nvarchar(1024)") - .HasColumnName("docpath"); - - b.Property("ExecId") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasColumnName("exec_id"); - - b.Property("ExecTimestamp") - .HasColumnType("datetimeoffset") - .HasColumnName("exec_timestamp"); - - b.Property("HostUsername") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasColumnName("host_user"); - - b.Property("IsConfig") - .HasColumnType("bit") - .HasColumnName("config"); - - b.Property("IsDebug") - .HasColumnType("bit") - .HasColumnName("debug"); - - b.Property("IsExecFromGui") - .HasColumnType("bit") - .HasColumnName("from_gui"); - - b.Property("Meta") - .IsRequired() - .HasColumnType("nvarchar(max)") - .HasColumnName("meta"); - - b.Property("PyRevitVersion") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasColumnName("pyrevit"); - - b.Property("ResultCode") - .HasColumnType("int") - .HasColumnName("resultcode"); - - b.Property("RevitBuild") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasColumnName("revitbuild"); - - b.Property("RevitVersion") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasColumnName("revit"); - - b.Property("ScriptPath") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("nvarchar(1024)") - .HasColumnName("scriptpath"); - - b.Property("SessionId") - .HasColumnType("uniqueidentifier") - .HasColumnName("sessionid"); - - b.Property("Timestamp") - .HasColumnType("datetimeoffset") - .HasColumnName("timestamp"); - - b.Property("Trace") - .IsRequired() - .HasColumnType("nvarchar(max)") - .HasColumnName("trace"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasColumnName("username"); - - b.HasKey("Id"); - - b.ToTable("script_record", (string)null); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Telemetry.Migrations.SqlServer/Migrations/20260330090733_InitSqlServer.cs b/src/Telemetry.Migrations.SqlServer/Migrations/20260330090733_InitSqlServer.cs deleted file mode 100644 index bb9b7b6..0000000 --- a/src/Telemetry.Migrations.SqlServer/Migrations/20260330090733_InitSqlServer.cs +++ /dev/null @@ -1,90 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Telemetry.Migrations.SqlServer.Migrations -{ - /// - public partial class InitSqlServer : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "event_record", - columns: table => new - { - id = table.Column(type: "uniqueidentifier", nullable: false), - handler_id = table.Column(type: "uniqueidentifier", nullable: false), - meta = table.Column(type: "nvarchar(max)", nullable: false), - type = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: false), - status = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: true), - timestamp = table.Column(type: "datetimeoffset", nullable: false), - username = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: false), - host_user = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: true), - revitbuild = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: false), - revit = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: false), - cancelled = table.Column(type: "bit", nullable: true), - Cancellable = table.Column(type: "bit", nullable: true), - docid = table.Column(type: "int", nullable: false), - doctype = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: true), - doctemplate = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: true), - docname = table.Column(type: "nvarchar(250)", maxLength: 250, nullable: true), - docpath = table.Column(type: "nvarchar(1024)", maxLength: 1024, nullable: true), - projectname = table.Column(type: "nvarchar(250)", maxLength: 250, nullable: true), - projectnum = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: true), - args = table.Column(type: "nvarchar(max)", maxLength: 8000, nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_event_record", x => x.id); - }); - - migrationBuilder.CreateTable( - name: "script_record", - columns: table => new - { - id = table.Column(type: "uniqueidentifier", nullable: false), - sessionid = table.Column(type: "uniqueidentifier", nullable: false), - meta = table.Column(type: "nvarchar(max)", nullable: false), - timestamp = table.Column(type: "datetimeoffset", nullable: false), - username = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: false), - host_user = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: true), - revitbuild = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: false), - revit = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: false), - pyrevit = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: false), - clone = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: false), - debug = table.Column(type: "bit", nullable: false), - config = table.Column(type: "bit", nullable: false), - from_gui = table.Column(type: "bit", nullable: false), - exec_id = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: false), - exec_timestamp = table.Column(type: "datetimeoffset", nullable: false), - commandbundle = table.Column(type: "nvarchar(250)", maxLength: 250, nullable: false), - commandextension = table.Column(type: "nvarchar(250)", maxLength: 250, nullable: false), - commandname = table.Column(type: "nvarchar(250)", maxLength: 250, nullable: false), - commanduniquename = table.Column(type: "nvarchar(500)", maxLength: 500, nullable: false), - docname = table.Column(type: "nvarchar(250)", maxLength: 250, nullable: true), - docpath = table.Column(type: "nvarchar(1024)", maxLength: 1024, nullable: true), - resultcode = table.Column(type: "int", nullable: false), - scriptpath = table.Column(type: "nvarchar(1024)", maxLength: 1024, nullable: false), - trace = table.Column(type: "nvarchar(max)", nullable: false), - commandresults = table.Column(type: "nvarchar(max)", maxLength: 8000, nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_script_record", x => x.id); - }); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "event_record"); - - migrationBuilder.DropTable( - name: "script_record"); - } - } -} diff --git a/src/Telemetry.Migrations.SqlServer/Migrations/20260402141635_AddCancellableSqlServer.Designer.cs b/src/Telemetry.Migrations.SqlServer/Migrations/20260402141635_AddCancellableSqlServer.Designer.cs deleted file mode 100644 index 9c2b98d..0000000 --- a/src/Telemetry.Migrations.SqlServer/Migrations/20260402141635_AddCancellableSqlServer.Designer.cs +++ /dev/null @@ -1,272 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Telemetry.Api.Infrastructure.Persistence; - -#nullable disable - -namespace Telemetry.Migrations.SqlServer.Migrations -{ - [DbContext(typeof(ApplicationDbContext))] - [Migration("20260402141635_AddCancellableSqlServer")] - partial class AddCancellableSqlServer - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "10.0.5") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - - modelBuilder.Entity("Telemetry.Api.Domain.Models.EventRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier") - .HasColumnName("id"); - - b.Property("Cancellable") - .HasColumnType("bit") - .HasColumnName("cancellable"); - - b.Property("Cancelled") - .HasColumnType("bit") - .HasColumnName("cancelled"); - - b.Property("DocumentId") - .HasColumnType("int") - .HasColumnName("docid"); - - b.Property("DocumentName") - .HasMaxLength(250) - .HasColumnType("nvarchar(250)") - .HasColumnName("docname"); - - b.Property("DocumentPath") - .HasMaxLength(1024) - .HasColumnType("nvarchar(1024)") - .HasColumnName("docpath"); - - b.Property("DocumentTemplate") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasColumnName("doctemplate"); - - b.Property("DocumentType") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasColumnName("doctype"); - - b.Property("EventArgs") - .HasMaxLength(8000) - .HasColumnType("nvarchar(max)") - .HasColumnName("args"); - - b.Property("EventType") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasColumnName("type"); - - b.Property("HandlerId") - .HasColumnType("uniqueidentifier") - .HasColumnName("handler_id"); - - b.Property("HostUsername") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasColumnName("host_user"); - - b.Property("Meta") - .IsRequired() - .HasColumnType("nvarchar(max)") - .HasColumnName("meta"); - - b.Property("ProjectName") - .HasMaxLength(250) - .HasColumnType("nvarchar(250)") - .HasColumnName("projectname"); - - b.Property("ProjectNum") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasColumnName("projectnum"); - - b.Property("RevitBuild") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasColumnName("revitbuild"); - - b.Property("RevitVersion") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasColumnName("revit"); - - b.Property("Status") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasColumnName("status"); - - b.Property("Timestamp") - .HasColumnType("datetimeoffset") - .HasColumnName("timestamp"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasColumnName("username"); - - b.HasKey("Id"); - - b.ToTable("event_record", (string)null); - }); - - modelBuilder.Entity("Telemetry.Api.Domain.Models.ScriptRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier") - .HasColumnName("id"); - - b.Property("CloneName") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasColumnName("clone"); - - b.Property("CommandBundle") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("nvarchar(250)") - .HasColumnName("commandbundle"); - - b.Property("CommandExtension") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("nvarchar(250)") - .HasColumnName("commandextension"); - - b.Property("CommandName") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("nvarchar(250)") - .HasColumnName("commandname"); - - b.Property("CommandResults") - .HasMaxLength(8000) - .HasColumnType("nvarchar(max)") - .HasColumnName("commandresults"); - - b.Property("CommandUniqueName") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("nvarchar(500)") - .HasColumnName("commanduniquename"); - - b.Property("DocumentName") - .HasMaxLength(250) - .HasColumnType("nvarchar(250)") - .HasColumnName("docname"); - - b.Property("DocumentPath") - .HasMaxLength(1024) - .HasColumnType("nvarchar(1024)") - .HasColumnName("docpath"); - - b.Property("ExecId") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasColumnName("exec_id"); - - b.Property("ExecTimestamp") - .HasColumnType("datetimeoffset") - .HasColumnName("exec_timestamp"); - - b.Property("HostUsername") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasColumnName("host_user"); - - b.Property("IsConfig") - .HasColumnType("bit") - .HasColumnName("config"); - - b.Property("IsDebug") - .HasColumnType("bit") - .HasColumnName("debug"); - - b.Property("IsExecFromGui") - .HasColumnType("bit") - .HasColumnName("from_gui"); - - b.Property("Meta") - .IsRequired() - .HasColumnType("nvarchar(max)") - .HasColumnName("meta"); - - b.Property("PyRevitVersion") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasColumnName("pyrevit"); - - b.Property("ResultCode") - .HasColumnType("int") - .HasColumnName("resultcode"); - - b.Property("RevitBuild") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasColumnName("revitbuild"); - - b.Property("RevitVersion") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasColumnName("revit"); - - b.Property("ScriptPath") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("nvarchar(1024)") - .HasColumnName("scriptpath"); - - b.Property("SessionId") - .HasColumnType("uniqueidentifier") - .HasColumnName("sessionid"); - - b.Property("Timestamp") - .HasColumnType("datetimeoffset") - .HasColumnName("timestamp"); - - b.Property("Trace") - .IsRequired() - .HasColumnType("nvarchar(max)") - .HasColumnName("trace"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasColumnName("username"); - - b.HasKey("Id"); - - b.ToTable("script_record", (string)null); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Telemetry.Migrations.SqlServer/Migrations/20260402141635_AddCancellableSqlServer.cs b/src/Telemetry.Migrations.SqlServer/Migrations/20260402141635_AddCancellableSqlServer.cs deleted file mode 100644 index 41f8ba0..0000000 --- a/src/Telemetry.Migrations.SqlServer/Migrations/20260402141635_AddCancellableSqlServer.cs +++ /dev/null @@ -1,28 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Telemetry.Migrations.SqlServer.Migrations -{ - /// - public partial class AddCancellableSqlServer : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.RenameColumn( - name: "Cancellable", - table: "event_record", - newName: "cancellable"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.RenameColumn( - name: "cancellable", - table: "event_record", - newName: "Cancellable"); - } - } -} diff --git a/src/Telemetry.Migrations.SqlServer/Migrations/20260406102100_UpdateDynamicDataSqlServer.Designer.cs b/src/Telemetry.Migrations.SqlServer/Migrations/20260406102100_UpdateDynamicDataSqlServer.Designer.cs deleted file mode 100644 index 3d60a45..0000000 --- a/src/Telemetry.Migrations.SqlServer/Migrations/20260406102100_UpdateDynamicDataSqlServer.Designer.cs +++ /dev/null @@ -1,321 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Telemetry.Api.Infrastructure.Persistence; - -#nullable disable - -namespace Telemetry.Migrations.SqlServer.Migrations -{ - [DbContext(typeof(ApplicationDbContext))] - [Migration("20260406102100_UpdateDynamicDataSqlServer")] - partial class UpdateDynamicDataSqlServer - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "10.0.5") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - - modelBuilder.Entity("Telemetry.Api.Domain.Models.EventRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier") - .HasColumnName("_id") - .HasAnnotation("Mongo:ElementName", "_id"); - - b.Property("Cancellable") - .HasColumnType("bit") - .HasColumnName("cancellable") - .HasAnnotation("Mongo:ElementName", "cancellable"); - - b.Property("Cancelled") - .HasColumnType("bit") - .HasColumnName("cancelled") - .HasAnnotation("Mongo:ElementName", "cancelled"); - - b.Property("DocumentId") - .HasColumnType("int") - .HasColumnName("docid") - .HasAnnotation("Mongo:ElementName", "docid"); - - b.Property("DocumentName") - .HasMaxLength(250) - .HasColumnType("nvarchar(250)") - .HasColumnName("docname") - .HasAnnotation("Mongo:ElementName", "docname"); - - b.Property("DocumentPath") - .HasMaxLength(1024) - .HasColumnType("nvarchar(1024)") - .HasColumnName("docpath") - .HasAnnotation("Mongo:ElementName", "docpath"); - - b.Property("DocumentTemplate") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasColumnName("doctemplate") - .HasAnnotation("Mongo:ElementName", "doctemplate"); - - b.Property("DocumentType") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasColumnName("doctype") - .HasAnnotation("Mongo:ElementName", "doctype"); - - b.Property("EventArgs") - .HasMaxLength(8000) - .HasColumnType("nvarchar(max)") - .HasColumnName("args") - .HasAnnotation("Mongo:ElementName", "args"); - - b.Property("EventType") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasColumnName("type") - .HasAnnotation("Mongo:ElementName", "type"); - - b.Property("HandlerId") - .HasColumnType("uniqueidentifier") - .HasColumnName("handler_id") - .HasAnnotation("Mongo:ElementName", "handler_id"); - - b.Property("HostUsername") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasColumnName("host_user") - .HasAnnotation("Mongo:ElementName", "host_user"); - - b.Property("Meta") - .IsRequired() - .HasColumnType("nvarchar(max)") - .HasColumnName("meta") - .HasAnnotation("Mongo:ElementName", "meta"); - - b.Property("ProjectName") - .HasMaxLength(250) - .HasColumnType("nvarchar(250)") - .HasColumnName("projectname") - .HasAnnotation("Mongo:ElementName", "projectname"); - - b.Property("ProjectNum") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasColumnName("projectnum") - .HasAnnotation("Mongo:ElementName", "projectnum"); - - b.Property("RevitBuild") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasColumnName("revitbuild") - .HasAnnotation("Mongo:ElementName", "revitbuild"); - - b.Property("RevitVersion") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasColumnName("revit") - .HasAnnotation("Mongo:ElementName", "revit"); - - b.Property("Status") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasColumnName("status") - .HasAnnotation("Mongo:ElementName", "status"); - - b.Property("Timestamp") - .HasColumnType("datetimeoffset") - .HasColumnName("timestamp") - .HasAnnotation("Mongo:ElementName", "timestamp"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasColumnName("username") - .HasAnnotation("Mongo:ElementName", "username"); - - b.HasKey("Id"); - - b.ToTable("events", (string)null); - - b.HasAnnotation("Mongo:CollectionName", "events"); - }); - - modelBuilder.Entity("Telemetry.Api.Domain.Models.ScriptRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier") - .HasColumnName("_id") - .HasAnnotation("Mongo:ElementName", "_id"); - - b.Property("CloneName") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasColumnName("clone") - .HasAnnotation("Mongo:ElementName", "clone"); - - b.Property("CommandBundle") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("nvarchar(250)") - .HasColumnName("commandbundle") - .HasAnnotation("Mongo:ElementName", "commandbundle"); - - b.Property("CommandExtension") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("nvarchar(250)") - .HasColumnName("commandextension") - .HasAnnotation("Mongo:ElementName", "commandextension"); - - b.Property("CommandName") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("nvarchar(250)") - .HasColumnName("commandname") - .HasAnnotation("Mongo:ElementName", "commandname"); - - b.Property("CommandResults") - .HasMaxLength(8000) - .HasColumnType("nvarchar(max)") - .HasColumnName("commandresults") - .HasAnnotation("Mongo:ElementName", "commandresults"); - - b.Property("CommandUniqueName") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("nvarchar(500)") - .HasColumnName("commanduniquename") - .HasAnnotation("Mongo:ElementName", "commanduniquename"); - - b.Property("DocumentName") - .HasMaxLength(250) - .HasColumnType("nvarchar(250)") - .HasColumnName("docname") - .HasAnnotation("Mongo:ElementName", "docname"); - - b.Property("DocumentPath") - .HasMaxLength(1024) - .HasColumnType("nvarchar(1024)") - .HasColumnName("docpath") - .HasAnnotation("Mongo:ElementName", "docpath"); - - b.Property("ExecId") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasColumnName("exec_id") - .HasAnnotation("Mongo:ElementName", "exec_id"); - - b.Property("ExecTimestamp") - .HasColumnType("datetimeoffset") - .HasColumnName("exec_timestamp") - .HasAnnotation("Mongo:ElementName", "exec_timestamp"); - - b.Property("HostUsername") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasColumnName("host_user") - .HasAnnotation("Mongo:ElementName", "host_user"); - - b.Property("IsConfig") - .HasColumnType("bit") - .HasColumnName("config") - .HasAnnotation("Mongo:ElementName", "config"); - - b.Property("IsDebug") - .HasColumnType("bit") - .HasColumnName("debug") - .HasAnnotation("Mongo:ElementName", "debug"); - - b.Property("IsExecFromGui") - .HasColumnType("bit") - .HasColumnName("from_gui") - .HasAnnotation("Mongo:ElementName", "from_gui"); - - b.Property("Meta") - .IsRequired() - .HasColumnType("nvarchar(max)") - .HasColumnName("meta") - .HasAnnotation("Mongo:ElementName", "meta"); - - b.Property("PyRevitVersion") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasColumnName("pyrevit") - .HasAnnotation("Mongo:ElementName", "pyrevit"); - - b.Property("ResultCode") - .HasColumnType("int") - .HasColumnName("resultcode") - .HasAnnotation("Mongo:ElementName", "resultcode"); - - b.Property("RevitBuild") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasColumnName("revitbuild") - .HasAnnotation("Mongo:ElementName", "revitbuild"); - - b.Property("RevitVersion") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasColumnName("revit") - .HasAnnotation("Mongo:ElementName", "revit"); - - b.Property("ScriptPath") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("nvarchar(1024)") - .HasColumnName("scriptpath") - .HasAnnotation("Mongo:ElementName", "scriptpath"); - - b.Property("SessionId") - .HasColumnType("uniqueidentifier") - .HasColumnName("sessionid") - .HasAnnotation("Mongo:ElementName", "sessionid"); - - b.Property("Timestamp") - .HasColumnType("datetimeoffset") - .HasColumnName("timestamp") - .HasAnnotation("Mongo:ElementName", "timestamp"); - - b.Property("Trace") - .IsRequired() - .HasColumnType("nvarchar(max)") - .HasColumnName("trace") - .HasAnnotation("Mongo:ElementName", "trace"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasColumnName("username") - .HasAnnotation("Mongo:ElementName", "username"); - - b.HasKey("Id"); - - b.ToTable("scripts", (string)null); - - b.HasAnnotation("Mongo:CollectionName", "scripts"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Telemetry.Migrations.SqlServer/Migrations/20260406102100_UpdateDynamicDataSqlServer.cs b/src/Telemetry.Migrations.SqlServer/Migrations/20260406102100_UpdateDynamicDataSqlServer.cs deleted file mode 100644 index b940889..0000000 --- a/src/Telemetry.Migrations.SqlServer/Migrations/20260406102100_UpdateDynamicDataSqlServer.cs +++ /dev/null @@ -1,90 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Telemetry.Migrations.SqlServer.Migrations -{ - /// - public partial class UpdateDynamicDataSqlServer : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropPrimaryKey( - name: "PK_script_record", - table: "script_record"); - - migrationBuilder.DropPrimaryKey( - name: "PK_event_record", - table: "event_record"); - - migrationBuilder.RenameTable( - name: "script_record", - newName: "scripts"); - - migrationBuilder.RenameTable( - name: "event_record", - newName: "events"); - - migrationBuilder.RenameColumn( - name: "id", - table: "scripts", - newName: "_id"); - - migrationBuilder.RenameColumn( - name: "id", - table: "events", - newName: "_id"); - - migrationBuilder.AddPrimaryKey( - name: "PK_scripts", - table: "scripts", - column: "_id"); - - migrationBuilder.AddPrimaryKey( - name: "PK_events", - table: "events", - column: "_id"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropPrimaryKey( - name: "PK_scripts", - table: "scripts"); - - migrationBuilder.DropPrimaryKey( - name: "PK_events", - table: "events"); - - migrationBuilder.RenameTable( - name: "scripts", - newName: "script_record"); - - migrationBuilder.RenameTable( - name: "events", - newName: "event_record"); - - migrationBuilder.RenameColumn( - name: "_id", - table: "script_record", - newName: "id"); - - migrationBuilder.RenameColumn( - name: "_id", - table: "event_record", - newName: "id"); - - migrationBuilder.AddPrimaryKey( - name: "PK_script_record", - table: "script_record", - column: "id"); - - migrationBuilder.AddPrimaryKey( - name: "PK_event_record", - table: "event_record", - column: "id"); - } - } -} diff --git a/src/Telemetry.Migrations.SqlServer/Migrations/ApplicationDbContextModelSnapshot.cs b/src/Telemetry.Migrations.SqlServer/Migrations/ApplicationDbContextModelSnapshot.cs deleted file mode 100644 index 0a97dea..0000000 --- a/src/Telemetry.Migrations.SqlServer/Migrations/ApplicationDbContextModelSnapshot.cs +++ /dev/null @@ -1,318 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Telemetry.Api.Infrastructure.Persistence; - -#nullable disable - -namespace Telemetry.Migrations.SqlServer.Migrations -{ - [DbContext(typeof(ApplicationDbContext))] - partial class ApplicationDbContextModelSnapshot : ModelSnapshot - { - protected override void BuildModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "10.0.5") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - - modelBuilder.Entity("Telemetry.Api.Domain.Models.EventRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier") - .HasColumnName("_id") - .HasAnnotation("Mongo:ElementName", "_id"); - - b.Property("Cancellable") - .HasColumnType("bit") - .HasColumnName("cancellable") - .HasAnnotation("Mongo:ElementName", "cancellable"); - - b.Property("Cancelled") - .HasColumnType("bit") - .HasColumnName("cancelled") - .HasAnnotation("Mongo:ElementName", "cancelled"); - - b.Property("DocumentId") - .HasColumnType("int") - .HasColumnName("docid") - .HasAnnotation("Mongo:ElementName", "docid"); - - b.Property("DocumentName") - .HasMaxLength(250) - .HasColumnType("nvarchar(250)") - .HasColumnName("docname") - .HasAnnotation("Mongo:ElementName", "docname"); - - b.Property("DocumentPath") - .HasMaxLength(1024) - .HasColumnType("nvarchar(1024)") - .HasColumnName("docpath") - .HasAnnotation("Mongo:ElementName", "docpath"); - - b.Property("DocumentTemplate") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasColumnName("doctemplate") - .HasAnnotation("Mongo:ElementName", "doctemplate"); - - b.Property("DocumentType") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasColumnName("doctype") - .HasAnnotation("Mongo:ElementName", "doctype"); - - b.Property("EventArgs") - .HasMaxLength(8000) - .HasColumnType("nvarchar(max)") - .HasColumnName("args") - .HasAnnotation("Mongo:ElementName", "args"); - - b.Property("EventType") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasColumnName("type") - .HasAnnotation("Mongo:ElementName", "type"); - - b.Property("HandlerId") - .HasColumnType("uniqueidentifier") - .HasColumnName("handler_id") - .HasAnnotation("Mongo:ElementName", "handler_id"); - - b.Property("HostUsername") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasColumnName("host_user") - .HasAnnotation("Mongo:ElementName", "host_user"); - - b.Property("Meta") - .IsRequired() - .HasColumnType("nvarchar(max)") - .HasColumnName("meta") - .HasAnnotation("Mongo:ElementName", "meta"); - - b.Property("ProjectName") - .HasMaxLength(250) - .HasColumnType("nvarchar(250)") - .HasColumnName("projectname") - .HasAnnotation("Mongo:ElementName", "projectname"); - - b.Property("ProjectNum") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasColumnName("projectnum") - .HasAnnotation("Mongo:ElementName", "projectnum"); - - b.Property("RevitBuild") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasColumnName("revitbuild") - .HasAnnotation("Mongo:ElementName", "revitbuild"); - - b.Property("RevitVersion") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasColumnName("revit") - .HasAnnotation("Mongo:ElementName", "revit"); - - b.Property("Status") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasColumnName("status") - .HasAnnotation("Mongo:ElementName", "status"); - - b.Property("Timestamp") - .HasColumnType("datetimeoffset") - .HasColumnName("timestamp") - .HasAnnotation("Mongo:ElementName", "timestamp"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasColumnName("username") - .HasAnnotation("Mongo:ElementName", "username"); - - b.HasKey("Id"); - - b.ToTable("events", (string)null); - - b.HasAnnotation("Mongo:CollectionName", "events"); - }); - - modelBuilder.Entity("Telemetry.Api.Domain.Models.ScriptRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier") - .HasColumnName("_id") - .HasAnnotation("Mongo:ElementName", "_id"); - - b.Property("CloneName") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasColumnName("clone") - .HasAnnotation("Mongo:ElementName", "clone"); - - b.Property("CommandBundle") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("nvarchar(250)") - .HasColumnName("commandbundle") - .HasAnnotation("Mongo:ElementName", "commandbundle"); - - b.Property("CommandExtension") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("nvarchar(250)") - .HasColumnName("commandextension") - .HasAnnotation("Mongo:ElementName", "commandextension"); - - b.Property("CommandName") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("nvarchar(250)") - .HasColumnName("commandname") - .HasAnnotation("Mongo:ElementName", "commandname"); - - b.Property("CommandResults") - .HasMaxLength(8000) - .HasColumnType("nvarchar(max)") - .HasColumnName("commandresults") - .HasAnnotation("Mongo:ElementName", "commandresults"); - - b.Property("CommandUniqueName") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("nvarchar(500)") - .HasColumnName("commanduniquename") - .HasAnnotation("Mongo:ElementName", "commanduniquename"); - - b.Property("DocumentName") - .HasMaxLength(250) - .HasColumnType("nvarchar(250)") - .HasColumnName("docname") - .HasAnnotation("Mongo:ElementName", "docname"); - - b.Property("DocumentPath") - .HasMaxLength(1024) - .HasColumnType("nvarchar(1024)") - .HasColumnName("docpath") - .HasAnnotation("Mongo:ElementName", "docpath"); - - b.Property("ExecId") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasColumnName("exec_id") - .HasAnnotation("Mongo:ElementName", "exec_id"); - - b.Property("ExecTimestamp") - .HasColumnType("datetimeoffset") - .HasColumnName("exec_timestamp") - .HasAnnotation("Mongo:ElementName", "exec_timestamp"); - - b.Property("HostUsername") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasColumnName("host_user") - .HasAnnotation("Mongo:ElementName", "host_user"); - - b.Property("IsConfig") - .HasColumnType("bit") - .HasColumnName("config") - .HasAnnotation("Mongo:ElementName", "config"); - - b.Property("IsDebug") - .HasColumnType("bit") - .HasColumnName("debug") - .HasAnnotation("Mongo:ElementName", "debug"); - - b.Property("IsExecFromGui") - .HasColumnType("bit") - .HasColumnName("from_gui") - .HasAnnotation("Mongo:ElementName", "from_gui"); - - b.Property("Meta") - .IsRequired() - .HasColumnType("nvarchar(max)") - .HasColumnName("meta") - .HasAnnotation("Mongo:ElementName", "meta"); - - b.Property("PyRevitVersion") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasColumnName("pyrevit") - .HasAnnotation("Mongo:ElementName", "pyrevit"); - - b.Property("ResultCode") - .HasColumnType("int") - .HasColumnName("resultcode") - .HasAnnotation("Mongo:ElementName", "resultcode"); - - b.Property("RevitBuild") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasColumnName("revitbuild") - .HasAnnotation("Mongo:ElementName", "revitbuild"); - - b.Property("RevitVersion") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasColumnName("revit") - .HasAnnotation("Mongo:ElementName", "revit"); - - b.Property("ScriptPath") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("nvarchar(1024)") - .HasColumnName("scriptpath") - .HasAnnotation("Mongo:ElementName", "scriptpath"); - - b.Property("SessionId") - .HasColumnType("uniqueidentifier") - .HasColumnName("sessionid") - .HasAnnotation("Mongo:ElementName", "sessionid"); - - b.Property("Timestamp") - .HasColumnType("datetimeoffset") - .HasColumnName("timestamp") - .HasAnnotation("Mongo:ElementName", "timestamp"); - - b.Property("Trace") - .IsRequired() - .HasColumnType("nvarchar(max)") - .HasColumnName("trace") - .HasAnnotation("Mongo:ElementName", "trace"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasColumnName("username") - .HasAnnotation("Mongo:ElementName", "username"); - - b.HasKey("Id"); - - b.ToTable("scripts", (string)null); - - b.HasAnnotation("Mongo:CollectionName", "scripts"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Telemetry.Migrations.Sqlite/Migrations/20260330090723_InitSqlite.Designer.cs b/src/Telemetry.Migrations.Sqlite/Migrations/20260330090723_InitSqlite.Designer.cs deleted file mode 100644 index f23cca0..0000000 --- a/src/Telemetry.Migrations.Sqlite/Migrations/20260330090723_InitSqlite.Designer.cs +++ /dev/null @@ -1,266 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Telemetry.Api.Infrastructure.Persistence; - -#nullable disable - -namespace Telemetry.Migrations.Sqlite.Migrations -{ - [DbContext(typeof(ApplicationDbContext))] - [Migration("20260330090723_InitSqlite")] - partial class InitSqlite - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "10.0.5"); - - modelBuilder.Entity("Telemetry.Api.Domain.Models.EventRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT") - .HasColumnName("id"); - - b.Property("Cancellable") - .HasColumnType("INTEGER"); - - b.Property("Cancelled") - .HasColumnType("INTEGER") - .HasColumnName("cancelled"); - - b.Property("DocumentId") - .HasColumnType("INTEGER") - .HasColumnName("docid"); - - b.Property("DocumentName") - .HasMaxLength(250) - .HasColumnType("TEXT") - .HasColumnName("docname"); - - b.Property("DocumentPath") - .HasMaxLength(1024) - .HasColumnType("TEXT") - .HasColumnName("docpath"); - - b.Property("DocumentTemplate") - .HasMaxLength(100) - .HasColumnType("TEXT") - .HasColumnName("doctemplate"); - - b.Property("DocumentType") - .HasMaxLength(100) - .HasColumnType("TEXT") - .HasColumnName("doctype"); - - b.Property("EventArgs") - .HasMaxLength(8000) - .HasColumnType("TEXT") - .HasColumnName("args"); - - b.Property("EventType") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT") - .HasColumnName("type"); - - b.Property("HandlerId") - .HasColumnType("TEXT") - .HasColumnName("handler_id"); - - b.Property("HostUsername") - .HasMaxLength(100) - .HasColumnType("TEXT") - .HasColumnName("host_user"); - - b.Property("Meta") - .IsRequired() - .HasColumnType("TEXT") - .HasColumnName("meta"); - - b.Property("ProjectName") - .HasMaxLength(250) - .HasColumnType("TEXT") - .HasColumnName("projectname"); - - b.Property("ProjectNum") - .HasMaxLength(100) - .HasColumnType("TEXT") - .HasColumnName("projectnum"); - - b.Property("RevitBuild") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT") - .HasColumnName("revitbuild"); - - b.Property("RevitVersion") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT") - .HasColumnName("revit"); - - b.Property("Status") - .HasMaxLength(100) - .HasColumnType("TEXT") - .HasColumnName("status"); - - b.Property("Timestamp") - .HasColumnType("TEXT") - .HasColumnName("timestamp"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT") - .HasColumnName("username"); - - b.HasKey("Id"); - - b.ToTable("event_record", (string)null); - }); - - modelBuilder.Entity("Telemetry.Api.Domain.Models.ScriptRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT") - .HasColumnName("id"); - - b.Property("CloneName") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT") - .HasColumnName("clone"); - - b.Property("CommandBundle") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("TEXT") - .HasColumnName("commandbundle"); - - b.Property("CommandExtension") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("TEXT") - .HasColumnName("commandextension"); - - b.Property("CommandName") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("TEXT") - .HasColumnName("commandname"); - - b.Property("CommandResults") - .HasMaxLength(8000) - .HasColumnType("TEXT") - .HasColumnName("commandresults"); - - b.Property("CommandUniqueName") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("TEXT") - .HasColumnName("commanduniquename"); - - b.Property("DocumentName") - .HasMaxLength(250) - .HasColumnType("TEXT") - .HasColumnName("docname"); - - b.Property("DocumentPath") - .HasMaxLength(1024) - .HasColumnType("TEXT") - .HasColumnName("docpath"); - - b.Property("ExecId") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT") - .HasColumnName("exec_id"); - - b.Property("ExecTimestamp") - .HasColumnType("TEXT") - .HasColumnName("exec_timestamp"); - - b.Property("HostUsername") - .HasMaxLength(100) - .HasColumnType("TEXT") - .HasColumnName("host_user"); - - b.Property("IsConfig") - .HasColumnType("INTEGER") - .HasColumnName("config"); - - b.Property("IsDebug") - .HasColumnType("INTEGER") - .HasColumnName("debug"); - - b.Property("IsExecFromGui") - .HasColumnType("INTEGER") - .HasColumnName("from_gui"); - - b.Property("Meta") - .IsRequired() - .HasColumnType("TEXT") - .HasColumnName("meta"); - - b.Property("PyRevitVersion") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT") - .HasColumnName("pyrevit"); - - b.Property("ResultCode") - .HasColumnType("INTEGER") - .HasColumnName("resultcode"); - - b.Property("RevitBuild") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT") - .HasColumnName("revitbuild"); - - b.Property("RevitVersion") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT") - .HasColumnName("revit"); - - b.Property("ScriptPath") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("TEXT") - .HasColumnName("scriptpath"); - - b.Property("SessionId") - .HasColumnType("TEXT") - .HasColumnName("sessionid"); - - b.Property("Timestamp") - .HasColumnType("TEXT") - .HasColumnName("timestamp"); - - b.Property("Trace") - .IsRequired() - .HasColumnType("TEXT") - .HasColumnName("trace"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT") - .HasColumnName("username"); - - b.HasKey("Id"); - - b.ToTable("script_record", (string)null); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Telemetry.Migrations.Sqlite/Migrations/20260330090723_InitSqlite.cs b/src/Telemetry.Migrations.Sqlite/Migrations/20260330090723_InitSqlite.cs deleted file mode 100644 index cf58817..0000000 --- a/src/Telemetry.Migrations.Sqlite/Migrations/20260330090723_InitSqlite.cs +++ /dev/null @@ -1,90 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Telemetry.Migrations.Sqlite.Migrations -{ - /// - public partial class InitSqlite : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "event_record", - columns: table => new - { - id = table.Column(type: "TEXT", nullable: false), - handler_id = table.Column(type: "TEXT", nullable: false), - meta = table.Column(type: "TEXT", nullable: false), - type = table.Column(type: "TEXT", maxLength: 100, nullable: false), - status = table.Column(type: "TEXT", maxLength: 100, nullable: true), - timestamp = table.Column(type: "TEXT", nullable: false), - username = table.Column(type: "TEXT", maxLength: 100, nullable: false), - host_user = table.Column(type: "TEXT", maxLength: 100, nullable: true), - revitbuild = table.Column(type: "TEXT", maxLength: 100, nullable: false), - revit = table.Column(type: "TEXT", maxLength: 100, nullable: false), - cancelled = table.Column(type: "INTEGER", nullable: true), - Cancellable = table.Column(type: "INTEGER", nullable: true), - docid = table.Column(type: "INTEGER", nullable: false), - doctype = table.Column(type: "TEXT", maxLength: 100, nullable: true), - doctemplate = table.Column(type: "TEXT", maxLength: 100, nullable: true), - docname = table.Column(type: "TEXT", maxLength: 250, nullable: true), - docpath = table.Column(type: "TEXT", maxLength: 1024, nullable: true), - projectname = table.Column(type: "TEXT", maxLength: 250, nullable: true), - projectnum = table.Column(type: "TEXT", maxLength: 100, nullable: true), - args = table.Column(type: "TEXT", maxLength: 8000, nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_event_record", x => x.id); - }); - - migrationBuilder.CreateTable( - name: "script_record", - columns: table => new - { - id = table.Column(type: "TEXT", nullable: false), - sessionid = table.Column(type: "TEXT", nullable: false), - meta = table.Column(type: "TEXT", nullable: false), - timestamp = table.Column(type: "TEXT", nullable: false), - username = table.Column(type: "TEXT", maxLength: 100, nullable: false), - host_user = table.Column(type: "TEXT", maxLength: 100, nullable: true), - revitbuild = table.Column(type: "TEXT", maxLength: 100, nullable: false), - revit = table.Column(type: "TEXT", maxLength: 100, nullable: false), - pyrevit = table.Column(type: "TEXT", maxLength: 100, nullable: false), - clone = table.Column(type: "TEXT", maxLength: 100, nullable: false), - debug = table.Column(type: "INTEGER", nullable: false), - config = table.Column(type: "INTEGER", nullable: false), - from_gui = table.Column(type: "INTEGER", nullable: false), - exec_id = table.Column(type: "TEXT", maxLength: 100, nullable: false), - exec_timestamp = table.Column(type: "TEXT", nullable: false), - commandbundle = table.Column(type: "TEXT", maxLength: 250, nullable: false), - commandextension = table.Column(type: "TEXT", maxLength: 250, nullable: false), - commandname = table.Column(type: "TEXT", maxLength: 250, nullable: false), - commanduniquename = table.Column(type: "TEXT", maxLength: 500, nullable: false), - docname = table.Column(type: "TEXT", maxLength: 250, nullable: true), - docpath = table.Column(type: "TEXT", maxLength: 1024, nullable: true), - resultcode = table.Column(type: "INTEGER", nullable: false), - scriptpath = table.Column(type: "TEXT", maxLength: 1024, nullable: false), - trace = table.Column(type: "TEXT", nullable: false), - commandresults = table.Column(type: "TEXT", maxLength: 8000, nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_script_record", x => x.id); - }); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "event_record"); - - migrationBuilder.DropTable( - name: "script_record"); - } - } -} diff --git a/src/Telemetry.Migrations.Sqlite/Migrations/20260402141622_AddCancellableSqlite.Designer.cs b/src/Telemetry.Migrations.Sqlite/Migrations/20260402141622_AddCancellableSqlite.Designer.cs deleted file mode 100644 index 5371bf9..0000000 --- a/src/Telemetry.Migrations.Sqlite/Migrations/20260402141622_AddCancellableSqlite.Designer.cs +++ /dev/null @@ -1,267 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Telemetry.Api.Infrastructure.Persistence; - -#nullable disable - -namespace Telemetry.Migrations.Sqlite.Migrations -{ - [DbContext(typeof(ApplicationDbContext))] - [Migration("20260402141622_AddCancellableSqlite")] - partial class AddCancellableSqlite - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "10.0.5"); - - modelBuilder.Entity("Telemetry.Api.Domain.Models.EventRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT") - .HasColumnName("id"); - - b.Property("Cancellable") - .HasColumnType("INTEGER") - .HasColumnName("cancellable"); - - b.Property("Cancelled") - .HasColumnType("INTEGER") - .HasColumnName("cancelled"); - - b.Property("DocumentId") - .HasColumnType("INTEGER") - .HasColumnName("docid"); - - b.Property("DocumentName") - .HasMaxLength(250) - .HasColumnType("TEXT") - .HasColumnName("docname"); - - b.Property("DocumentPath") - .HasMaxLength(1024) - .HasColumnType("TEXT") - .HasColumnName("docpath"); - - b.Property("DocumentTemplate") - .HasMaxLength(100) - .HasColumnType("TEXT") - .HasColumnName("doctemplate"); - - b.Property("DocumentType") - .HasMaxLength(100) - .HasColumnType("TEXT") - .HasColumnName("doctype"); - - b.Property("EventArgs") - .HasMaxLength(8000) - .HasColumnType("TEXT") - .HasColumnName("args"); - - b.Property("EventType") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT") - .HasColumnName("type"); - - b.Property("HandlerId") - .HasColumnType("TEXT") - .HasColumnName("handler_id"); - - b.Property("HostUsername") - .HasMaxLength(100) - .HasColumnType("TEXT") - .HasColumnName("host_user"); - - b.Property("Meta") - .IsRequired() - .HasColumnType("TEXT") - .HasColumnName("meta"); - - b.Property("ProjectName") - .HasMaxLength(250) - .HasColumnType("TEXT") - .HasColumnName("projectname"); - - b.Property("ProjectNum") - .HasMaxLength(100) - .HasColumnType("TEXT") - .HasColumnName("projectnum"); - - b.Property("RevitBuild") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT") - .HasColumnName("revitbuild"); - - b.Property("RevitVersion") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT") - .HasColumnName("revit"); - - b.Property("Status") - .HasMaxLength(100) - .HasColumnType("TEXT") - .HasColumnName("status"); - - b.Property("Timestamp") - .HasColumnType("TEXT") - .HasColumnName("timestamp"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT") - .HasColumnName("username"); - - b.HasKey("Id"); - - b.ToTable("event_record", (string)null); - }); - - modelBuilder.Entity("Telemetry.Api.Domain.Models.ScriptRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT") - .HasColumnName("id"); - - b.Property("CloneName") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT") - .HasColumnName("clone"); - - b.Property("CommandBundle") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("TEXT") - .HasColumnName("commandbundle"); - - b.Property("CommandExtension") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("TEXT") - .HasColumnName("commandextension"); - - b.Property("CommandName") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("TEXT") - .HasColumnName("commandname"); - - b.Property("CommandResults") - .HasMaxLength(8000) - .HasColumnType("TEXT") - .HasColumnName("commandresults"); - - b.Property("CommandUniqueName") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("TEXT") - .HasColumnName("commanduniquename"); - - b.Property("DocumentName") - .HasMaxLength(250) - .HasColumnType("TEXT") - .HasColumnName("docname"); - - b.Property("DocumentPath") - .HasMaxLength(1024) - .HasColumnType("TEXT") - .HasColumnName("docpath"); - - b.Property("ExecId") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT") - .HasColumnName("exec_id"); - - b.Property("ExecTimestamp") - .HasColumnType("TEXT") - .HasColumnName("exec_timestamp"); - - b.Property("HostUsername") - .HasMaxLength(100) - .HasColumnType("TEXT") - .HasColumnName("host_user"); - - b.Property("IsConfig") - .HasColumnType("INTEGER") - .HasColumnName("config"); - - b.Property("IsDebug") - .HasColumnType("INTEGER") - .HasColumnName("debug"); - - b.Property("IsExecFromGui") - .HasColumnType("INTEGER") - .HasColumnName("from_gui"); - - b.Property("Meta") - .IsRequired() - .HasColumnType("TEXT") - .HasColumnName("meta"); - - b.Property("PyRevitVersion") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT") - .HasColumnName("pyrevit"); - - b.Property("ResultCode") - .HasColumnType("INTEGER") - .HasColumnName("resultcode"); - - b.Property("RevitBuild") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT") - .HasColumnName("revitbuild"); - - b.Property("RevitVersion") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT") - .HasColumnName("revit"); - - b.Property("ScriptPath") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("TEXT") - .HasColumnName("scriptpath"); - - b.Property("SessionId") - .HasColumnType("TEXT") - .HasColumnName("sessionid"); - - b.Property("Timestamp") - .HasColumnType("TEXT") - .HasColumnName("timestamp"); - - b.Property("Trace") - .IsRequired() - .HasColumnType("TEXT") - .HasColumnName("trace"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT") - .HasColumnName("username"); - - b.HasKey("Id"); - - b.ToTable("script_record", (string)null); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Telemetry.Migrations.Sqlite/Migrations/20260402141622_AddCancellableSqlite.cs b/src/Telemetry.Migrations.Sqlite/Migrations/20260402141622_AddCancellableSqlite.cs deleted file mode 100644 index 1ef0e39..0000000 --- a/src/Telemetry.Migrations.Sqlite/Migrations/20260402141622_AddCancellableSqlite.cs +++ /dev/null @@ -1,28 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Telemetry.Migrations.Sqlite.Migrations -{ - /// - public partial class AddCancellableSqlite : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.RenameColumn( - name: "Cancellable", - table: "event_record", - newName: "cancellable"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.RenameColumn( - name: "cancellable", - table: "event_record", - newName: "Cancellable"); - } - } -} diff --git a/src/Telemetry.Migrations.Sqlite/Migrations/20260406102040_UpdateDynamicDataSqlite.Designer.cs b/src/Telemetry.Migrations.Sqlite/Migrations/20260406102040_UpdateDynamicDataSqlite.Designer.cs deleted file mode 100644 index 0397734..0000000 --- a/src/Telemetry.Migrations.Sqlite/Migrations/20260406102040_UpdateDynamicDataSqlite.Designer.cs +++ /dev/null @@ -1,316 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Telemetry.Api.Infrastructure.Persistence; - -#nullable disable - -namespace Telemetry.Migrations.Sqlite.Migrations -{ - [DbContext(typeof(ApplicationDbContext))] - [Migration("20260406102040_UpdateDynamicDataSqlite")] - partial class UpdateDynamicDataSqlite - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "10.0.5"); - - modelBuilder.Entity("Telemetry.Api.Domain.Models.EventRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT") - .HasColumnName("_id") - .HasAnnotation("Mongo:ElementName", "_id"); - - b.Property("Cancellable") - .HasColumnType("INTEGER") - .HasColumnName("cancellable") - .HasAnnotation("Mongo:ElementName", "cancellable"); - - b.Property("Cancelled") - .HasColumnType("INTEGER") - .HasColumnName("cancelled") - .HasAnnotation("Mongo:ElementName", "cancelled"); - - b.Property("DocumentId") - .HasColumnType("INTEGER") - .HasColumnName("docid") - .HasAnnotation("Mongo:ElementName", "docid"); - - b.Property("DocumentName") - .HasMaxLength(250) - .HasColumnType("TEXT") - .HasColumnName("docname") - .HasAnnotation("Mongo:ElementName", "docname"); - - b.Property("DocumentPath") - .HasMaxLength(1024) - .HasColumnType("TEXT") - .HasColumnName("docpath") - .HasAnnotation("Mongo:ElementName", "docpath"); - - b.Property("DocumentTemplate") - .HasMaxLength(100) - .HasColumnType("TEXT") - .HasColumnName("doctemplate") - .HasAnnotation("Mongo:ElementName", "doctemplate"); - - b.Property("DocumentType") - .HasMaxLength(100) - .HasColumnType("TEXT") - .HasColumnName("doctype") - .HasAnnotation("Mongo:ElementName", "doctype"); - - b.Property("EventArgs") - .HasMaxLength(8000) - .HasColumnType("TEXT") - .HasColumnName("args") - .HasAnnotation("Mongo:ElementName", "args"); - - b.Property("EventType") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT") - .HasColumnName("type") - .HasAnnotation("Mongo:ElementName", "type"); - - b.Property("HandlerId") - .HasColumnType("TEXT") - .HasColumnName("handler_id") - .HasAnnotation("Mongo:ElementName", "handler_id"); - - b.Property("HostUsername") - .HasMaxLength(100) - .HasColumnType("TEXT") - .HasColumnName("host_user") - .HasAnnotation("Mongo:ElementName", "host_user"); - - b.Property("Meta") - .IsRequired() - .HasColumnType("TEXT") - .HasColumnName("meta") - .HasAnnotation("Mongo:ElementName", "meta"); - - b.Property("ProjectName") - .HasMaxLength(250) - .HasColumnType("TEXT") - .HasColumnName("projectname") - .HasAnnotation("Mongo:ElementName", "projectname"); - - b.Property("ProjectNum") - .HasMaxLength(100) - .HasColumnType("TEXT") - .HasColumnName("projectnum") - .HasAnnotation("Mongo:ElementName", "projectnum"); - - b.Property("RevitBuild") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT") - .HasColumnName("revitbuild") - .HasAnnotation("Mongo:ElementName", "revitbuild"); - - b.Property("RevitVersion") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT") - .HasColumnName("revit") - .HasAnnotation("Mongo:ElementName", "revit"); - - b.Property("Status") - .HasMaxLength(100) - .HasColumnType("TEXT") - .HasColumnName("status") - .HasAnnotation("Mongo:ElementName", "status"); - - b.Property("Timestamp") - .HasColumnType("TEXT") - .HasColumnName("timestamp") - .HasAnnotation("Mongo:ElementName", "timestamp"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT") - .HasColumnName("username") - .HasAnnotation("Mongo:ElementName", "username"); - - b.HasKey("Id"); - - b.ToTable("events", (string)null); - - b.HasAnnotation("Mongo:CollectionName", "events"); - }); - - modelBuilder.Entity("Telemetry.Api.Domain.Models.ScriptRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT") - .HasColumnName("_id") - .HasAnnotation("Mongo:ElementName", "_id"); - - b.Property("CloneName") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT") - .HasColumnName("clone") - .HasAnnotation("Mongo:ElementName", "clone"); - - b.Property("CommandBundle") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("TEXT") - .HasColumnName("commandbundle") - .HasAnnotation("Mongo:ElementName", "commandbundle"); - - b.Property("CommandExtension") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("TEXT") - .HasColumnName("commandextension") - .HasAnnotation("Mongo:ElementName", "commandextension"); - - b.Property("CommandName") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("TEXT") - .HasColumnName("commandname") - .HasAnnotation("Mongo:ElementName", "commandname"); - - b.Property("CommandResults") - .HasMaxLength(8000) - .HasColumnType("TEXT") - .HasColumnName("commandresults") - .HasAnnotation("Mongo:ElementName", "commandresults"); - - b.Property("CommandUniqueName") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("TEXT") - .HasColumnName("commanduniquename") - .HasAnnotation("Mongo:ElementName", "commanduniquename"); - - b.Property("DocumentName") - .HasMaxLength(250) - .HasColumnType("TEXT") - .HasColumnName("docname") - .HasAnnotation("Mongo:ElementName", "docname"); - - b.Property("DocumentPath") - .HasMaxLength(1024) - .HasColumnType("TEXT") - .HasColumnName("docpath") - .HasAnnotation("Mongo:ElementName", "docpath"); - - b.Property("ExecId") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT") - .HasColumnName("exec_id") - .HasAnnotation("Mongo:ElementName", "exec_id"); - - b.Property("ExecTimestamp") - .HasColumnType("TEXT") - .HasColumnName("exec_timestamp") - .HasAnnotation("Mongo:ElementName", "exec_timestamp"); - - b.Property("HostUsername") - .HasMaxLength(100) - .HasColumnType("TEXT") - .HasColumnName("host_user") - .HasAnnotation("Mongo:ElementName", "host_user"); - - b.Property("IsConfig") - .HasColumnType("INTEGER") - .HasColumnName("config") - .HasAnnotation("Mongo:ElementName", "config"); - - b.Property("IsDebug") - .HasColumnType("INTEGER") - .HasColumnName("debug") - .HasAnnotation("Mongo:ElementName", "debug"); - - b.Property("IsExecFromGui") - .HasColumnType("INTEGER") - .HasColumnName("from_gui") - .HasAnnotation("Mongo:ElementName", "from_gui"); - - b.Property("Meta") - .IsRequired() - .HasColumnType("TEXT") - .HasColumnName("meta") - .HasAnnotation("Mongo:ElementName", "meta"); - - b.Property("PyRevitVersion") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT") - .HasColumnName("pyrevit") - .HasAnnotation("Mongo:ElementName", "pyrevit"); - - b.Property("ResultCode") - .HasColumnType("INTEGER") - .HasColumnName("resultcode") - .HasAnnotation("Mongo:ElementName", "resultcode"); - - b.Property("RevitBuild") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT") - .HasColumnName("revitbuild") - .HasAnnotation("Mongo:ElementName", "revitbuild"); - - b.Property("RevitVersion") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT") - .HasColumnName("revit") - .HasAnnotation("Mongo:ElementName", "revit"); - - b.Property("ScriptPath") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("TEXT") - .HasColumnName("scriptpath") - .HasAnnotation("Mongo:ElementName", "scriptpath"); - - b.Property("SessionId") - .HasColumnType("TEXT") - .HasColumnName("sessionid") - .HasAnnotation("Mongo:ElementName", "sessionid"); - - b.Property("Timestamp") - .HasColumnType("TEXT") - .HasColumnName("timestamp") - .HasAnnotation("Mongo:ElementName", "timestamp"); - - b.Property("Trace") - .IsRequired() - .HasColumnType("TEXT") - .HasColumnName("trace") - .HasAnnotation("Mongo:ElementName", "trace"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT") - .HasColumnName("username") - .HasAnnotation("Mongo:ElementName", "username"); - - b.HasKey("Id"); - - b.ToTable("scripts", (string)null); - - b.HasAnnotation("Mongo:CollectionName", "scripts"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Telemetry.Migrations.Sqlite/Migrations/20260406102040_UpdateDynamicDataSqlite.cs b/src/Telemetry.Migrations.Sqlite/Migrations/20260406102040_UpdateDynamicDataSqlite.cs deleted file mode 100644 index 7e0bcb0..0000000 --- a/src/Telemetry.Migrations.Sqlite/Migrations/20260406102040_UpdateDynamicDataSqlite.cs +++ /dev/null @@ -1,90 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Telemetry.Migrations.Sqlite.Migrations -{ - /// - public partial class UpdateDynamicDataSqlite : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropPrimaryKey( - name: "PK_script_record", - table: "script_record"); - - migrationBuilder.DropPrimaryKey( - name: "PK_event_record", - table: "event_record"); - - migrationBuilder.RenameTable( - name: "script_record", - newName: "scripts"); - - migrationBuilder.RenameTable( - name: "event_record", - newName: "events"); - - migrationBuilder.RenameColumn( - name: "id", - table: "scripts", - newName: "_id"); - - migrationBuilder.RenameColumn( - name: "id", - table: "events", - newName: "_id"); - - migrationBuilder.AddPrimaryKey( - name: "PK_scripts", - table: "scripts", - column: "_id"); - - migrationBuilder.AddPrimaryKey( - name: "PK_events", - table: "events", - column: "_id"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropPrimaryKey( - name: "PK_scripts", - table: "scripts"); - - migrationBuilder.DropPrimaryKey( - name: "PK_events", - table: "events"); - - migrationBuilder.RenameTable( - name: "scripts", - newName: "script_record"); - - migrationBuilder.RenameTable( - name: "events", - newName: "event_record"); - - migrationBuilder.RenameColumn( - name: "_id", - table: "script_record", - newName: "id"); - - migrationBuilder.RenameColumn( - name: "_id", - table: "event_record", - newName: "id"); - - migrationBuilder.AddPrimaryKey( - name: "PK_script_record", - table: "script_record", - column: "id"); - - migrationBuilder.AddPrimaryKey( - name: "PK_event_record", - table: "event_record", - column: "id"); - } - } -} diff --git a/src/Telemetry.Migrations.Sqlite/Migrations/ApplicationDbContextModelSnapshot.cs b/src/Telemetry.Migrations.Sqlite/Migrations/ApplicationDbContextModelSnapshot.cs deleted file mode 100644 index e90e216..0000000 --- a/src/Telemetry.Migrations.Sqlite/Migrations/ApplicationDbContextModelSnapshot.cs +++ /dev/null @@ -1,313 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Telemetry.Api.Infrastructure.Persistence; - -#nullable disable - -namespace Telemetry.Migrations.Sqlite.Migrations -{ - [DbContext(typeof(ApplicationDbContext))] - partial class ApplicationDbContextModelSnapshot : ModelSnapshot - { - protected override void BuildModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "10.0.5"); - - modelBuilder.Entity("Telemetry.Api.Domain.Models.EventRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT") - .HasColumnName("_id") - .HasAnnotation("Mongo:ElementName", "_id"); - - b.Property("Cancellable") - .HasColumnType("INTEGER") - .HasColumnName("cancellable") - .HasAnnotation("Mongo:ElementName", "cancellable"); - - b.Property("Cancelled") - .HasColumnType("INTEGER") - .HasColumnName("cancelled") - .HasAnnotation("Mongo:ElementName", "cancelled"); - - b.Property("DocumentId") - .HasColumnType("INTEGER") - .HasColumnName("docid") - .HasAnnotation("Mongo:ElementName", "docid"); - - b.Property("DocumentName") - .HasMaxLength(250) - .HasColumnType("TEXT") - .HasColumnName("docname") - .HasAnnotation("Mongo:ElementName", "docname"); - - b.Property("DocumentPath") - .HasMaxLength(1024) - .HasColumnType("TEXT") - .HasColumnName("docpath") - .HasAnnotation("Mongo:ElementName", "docpath"); - - b.Property("DocumentTemplate") - .HasMaxLength(100) - .HasColumnType("TEXT") - .HasColumnName("doctemplate") - .HasAnnotation("Mongo:ElementName", "doctemplate"); - - b.Property("DocumentType") - .HasMaxLength(100) - .HasColumnType("TEXT") - .HasColumnName("doctype") - .HasAnnotation("Mongo:ElementName", "doctype"); - - b.Property("EventArgs") - .HasMaxLength(8000) - .HasColumnType("TEXT") - .HasColumnName("args") - .HasAnnotation("Mongo:ElementName", "args"); - - b.Property("EventType") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT") - .HasColumnName("type") - .HasAnnotation("Mongo:ElementName", "type"); - - b.Property("HandlerId") - .HasColumnType("TEXT") - .HasColumnName("handler_id") - .HasAnnotation("Mongo:ElementName", "handler_id"); - - b.Property("HostUsername") - .HasMaxLength(100) - .HasColumnType("TEXT") - .HasColumnName("host_user") - .HasAnnotation("Mongo:ElementName", "host_user"); - - b.Property("Meta") - .IsRequired() - .HasColumnType("TEXT") - .HasColumnName("meta") - .HasAnnotation("Mongo:ElementName", "meta"); - - b.Property("ProjectName") - .HasMaxLength(250) - .HasColumnType("TEXT") - .HasColumnName("projectname") - .HasAnnotation("Mongo:ElementName", "projectname"); - - b.Property("ProjectNum") - .HasMaxLength(100) - .HasColumnType("TEXT") - .HasColumnName("projectnum") - .HasAnnotation("Mongo:ElementName", "projectnum"); - - b.Property("RevitBuild") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT") - .HasColumnName("revitbuild") - .HasAnnotation("Mongo:ElementName", "revitbuild"); - - b.Property("RevitVersion") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT") - .HasColumnName("revit") - .HasAnnotation("Mongo:ElementName", "revit"); - - b.Property("Status") - .HasMaxLength(100) - .HasColumnType("TEXT") - .HasColumnName("status") - .HasAnnotation("Mongo:ElementName", "status"); - - b.Property("Timestamp") - .HasColumnType("TEXT") - .HasColumnName("timestamp") - .HasAnnotation("Mongo:ElementName", "timestamp"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT") - .HasColumnName("username") - .HasAnnotation("Mongo:ElementName", "username"); - - b.HasKey("Id"); - - b.ToTable("events", (string)null); - - b.HasAnnotation("Mongo:CollectionName", "events"); - }); - - modelBuilder.Entity("Telemetry.Api.Domain.Models.ScriptRecord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT") - .HasColumnName("_id") - .HasAnnotation("Mongo:ElementName", "_id"); - - b.Property("CloneName") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT") - .HasColumnName("clone") - .HasAnnotation("Mongo:ElementName", "clone"); - - b.Property("CommandBundle") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("TEXT") - .HasColumnName("commandbundle") - .HasAnnotation("Mongo:ElementName", "commandbundle"); - - b.Property("CommandExtension") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("TEXT") - .HasColumnName("commandextension") - .HasAnnotation("Mongo:ElementName", "commandextension"); - - b.Property("CommandName") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("TEXT") - .HasColumnName("commandname") - .HasAnnotation("Mongo:ElementName", "commandname"); - - b.Property("CommandResults") - .HasMaxLength(8000) - .HasColumnType("TEXT") - .HasColumnName("commandresults") - .HasAnnotation("Mongo:ElementName", "commandresults"); - - b.Property("CommandUniqueName") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("TEXT") - .HasColumnName("commanduniquename") - .HasAnnotation("Mongo:ElementName", "commanduniquename"); - - b.Property("DocumentName") - .HasMaxLength(250) - .HasColumnType("TEXT") - .HasColumnName("docname") - .HasAnnotation("Mongo:ElementName", "docname"); - - b.Property("DocumentPath") - .HasMaxLength(1024) - .HasColumnType("TEXT") - .HasColumnName("docpath") - .HasAnnotation("Mongo:ElementName", "docpath"); - - b.Property("ExecId") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT") - .HasColumnName("exec_id") - .HasAnnotation("Mongo:ElementName", "exec_id"); - - b.Property("ExecTimestamp") - .HasColumnType("TEXT") - .HasColumnName("exec_timestamp") - .HasAnnotation("Mongo:ElementName", "exec_timestamp"); - - b.Property("HostUsername") - .HasMaxLength(100) - .HasColumnType("TEXT") - .HasColumnName("host_user") - .HasAnnotation("Mongo:ElementName", "host_user"); - - b.Property("IsConfig") - .HasColumnType("INTEGER") - .HasColumnName("config") - .HasAnnotation("Mongo:ElementName", "config"); - - b.Property("IsDebug") - .HasColumnType("INTEGER") - .HasColumnName("debug") - .HasAnnotation("Mongo:ElementName", "debug"); - - b.Property("IsExecFromGui") - .HasColumnType("INTEGER") - .HasColumnName("from_gui") - .HasAnnotation("Mongo:ElementName", "from_gui"); - - b.Property("Meta") - .IsRequired() - .HasColumnType("TEXT") - .HasColumnName("meta") - .HasAnnotation("Mongo:ElementName", "meta"); - - b.Property("PyRevitVersion") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT") - .HasColumnName("pyrevit") - .HasAnnotation("Mongo:ElementName", "pyrevit"); - - b.Property("ResultCode") - .HasColumnType("INTEGER") - .HasColumnName("resultcode") - .HasAnnotation("Mongo:ElementName", "resultcode"); - - b.Property("RevitBuild") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT") - .HasColumnName("revitbuild") - .HasAnnotation("Mongo:ElementName", "revitbuild"); - - b.Property("RevitVersion") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT") - .HasColumnName("revit") - .HasAnnotation("Mongo:ElementName", "revit"); - - b.Property("ScriptPath") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("TEXT") - .HasColumnName("scriptpath") - .HasAnnotation("Mongo:ElementName", "scriptpath"); - - b.Property("SessionId") - .HasColumnType("TEXT") - .HasColumnName("sessionid") - .HasAnnotation("Mongo:ElementName", "sessionid"); - - b.Property("Timestamp") - .HasColumnType("TEXT") - .HasColumnName("timestamp") - .HasAnnotation("Mongo:ElementName", "timestamp"); - - b.Property("Trace") - .IsRequired() - .HasColumnType("TEXT") - .HasColumnName("trace") - .HasAnnotation("Mongo:ElementName", "trace"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT") - .HasColumnName("username") - .HasAnnotation("Mongo:ElementName", "username"); - - b.HasKey("Id"); - - b.ToTable("scripts", (string)null); - - b.HasAnnotation("Mongo:CollectionName", "scripts"); - }); -#pragma warning restore 612, 618 - } - } -} From fb68054a41a39df50b2bf9f82ac6090709bab7ca Mon Sep 17 00:00:00 2001 From: dosymep Date: Mon, 6 Apr 2026 18:25:58 +0600 Subject: [PATCH 29/31] use native types --- .../Persistence/ApplicationDbContext.cs | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/Telemetry.Api/Infrastructure/Persistence/ApplicationDbContext.cs b/src/Telemetry.Api/Infrastructure/Persistence/ApplicationDbContext.cs index c1680d7..f9d0a80 100644 --- a/src/Telemetry.Api/Infrastructure/Persistence/ApplicationDbContext.cs +++ b/src/Telemetry.Api/Infrastructure/Persistence/ApplicationDbContext.cs @@ -171,7 +171,7 @@ private static void ConfigureMongoDbModel(ModelBuilder modelBuilder) }); } - private static void ConfigureSqlModel(ModelBuilder modelBuilder) + private void ConfigureSqlModel(ModelBuilder modelBuilder) { modelBuilder.Entity(entity => { @@ -181,16 +181,22 @@ private static void ConfigureSqlModel(ModelBuilder modelBuilder) trace.OwnsOne(e => e.Engine, engine => { + if (Database.IsOracle()) + { + engine.Property(e => e.Configs) + .HasColumnName(PropertyNames.EngineConfigs) + .HasColumnType("json"); + } + else if (Database.IsNpgsql()) + { + engine.Property(e => e.Configs) + .HasColumnName(PropertyNames.EngineConfigs) + .HasColumnType("jsonb"); + } + engine.Property(e => e.Type).HasColumnName(PropertyNames.EngineType); engine.Property(e => e.Version).HasColumnName(PropertyNames.EngineVersion); - engine.Property(e => e.Configs).HasColumnName(PropertyNames.EngineConfigs); - - engine.Property(e => e.SysPaths) - .HasColumnName(PropertyNames.EngineSysPaths) - .HasConversion( - v => v == null ? null : string.Join(";", v), - v => string.IsNullOrEmpty(v) ? null : v.Split(";") - ); + engine.Property(e => e.SysPaths).HasColumnName(PropertyNames.EngineSysPaths); }); }); }); From a9c2c4f53a990f78c4b8ba0d3930281aba2d6f71 Mon Sep 17 00:00:00 2001 From: dosymep Date: Mon, 6 Apr 2026 18:31:01 +0600 Subject: [PATCH 30/31] add initial migrations --- .../20260406123021_InitOracle.Designer.cs | 319 ++++++++++++++++++ .../Migrations/20260406123021_InitOracle.cs | 92 +++++ .../ApplicationDbContextModelSnapshot.cs | 316 +++++++++++++++++ .../20260406123028_InitPostgres.Designer.cs | 319 ++++++++++++++++++ .../Migrations/20260406123028_InitPostgres.cs | 92 +++++ .../ApplicationDbContextModelSnapshot.cs | 316 +++++++++++++++++ .../20260406123037_InitSqlServer.Designer.cs | 319 ++++++++++++++++++ .../20260406123037_InitSqlServer.cs | 92 +++++ .../ApplicationDbContextModelSnapshot.cs | 316 +++++++++++++++++ .../20260406123032_InitSqlite.Designer.cs | 314 +++++++++++++++++ .../Migrations/20260406123032_InitSqlite.cs | 92 +++++ .../ApplicationDbContextModelSnapshot.cs | 311 +++++++++++++++++ 12 files changed, 2898 insertions(+) create mode 100644 src/Telemetry.Migrations.Oracle/Migrations/20260406123021_InitOracle.Designer.cs create mode 100644 src/Telemetry.Migrations.Oracle/Migrations/20260406123021_InitOracle.cs create mode 100644 src/Telemetry.Migrations.Oracle/Migrations/ApplicationDbContextModelSnapshot.cs create mode 100644 src/Telemetry.Migrations.Postgres/Migrations/20260406123028_InitPostgres.Designer.cs create mode 100644 src/Telemetry.Migrations.Postgres/Migrations/20260406123028_InitPostgres.cs create mode 100644 src/Telemetry.Migrations.Postgres/Migrations/ApplicationDbContextModelSnapshot.cs create mode 100644 src/Telemetry.Migrations.SqlServer/Migrations/20260406123037_InitSqlServer.Designer.cs create mode 100644 src/Telemetry.Migrations.SqlServer/Migrations/20260406123037_InitSqlServer.cs create mode 100644 src/Telemetry.Migrations.SqlServer/Migrations/ApplicationDbContextModelSnapshot.cs create mode 100644 src/Telemetry.Migrations.Sqlite/Migrations/20260406123032_InitSqlite.Designer.cs create mode 100644 src/Telemetry.Migrations.Sqlite/Migrations/20260406123032_InitSqlite.cs create mode 100644 src/Telemetry.Migrations.Sqlite/Migrations/ApplicationDbContextModelSnapshot.cs diff --git a/src/Telemetry.Migrations.Oracle/Migrations/20260406123021_InitOracle.Designer.cs b/src/Telemetry.Migrations.Oracle/Migrations/20260406123021_InitOracle.Designer.cs new file mode 100644 index 0000000..2520eaf --- /dev/null +++ b/src/Telemetry.Migrations.Oracle/Migrations/20260406123021_InitOracle.Designer.cs @@ -0,0 +1,319 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Oracle.EntityFrameworkCore.Metadata; +using Telemetry.Api.Infrastructure.Persistence; + +#nullable disable + +namespace Telemetry.Migrations.Oracle.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20260406123021_InitOracle")] + partial class InitOracle + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "10.0.5") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + OracleModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Telemetry.Api.Domain.Models.EventRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("RAW(16)") + .HasColumnName("_id"); + + b.Property("Cancellable") + .HasColumnType("BOOLEAN") + .HasColumnName("cancellable"); + + b.Property("Cancelled") + .HasColumnType("BOOLEAN") + .HasColumnName("cancelled"); + + b.Property("DocumentId") + .HasColumnType("NUMBER(10)") + .HasColumnName("docid"); + + b.Property("DocumentName") + .HasMaxLength(250) + .HasColumnType("NVARCHAR2(250)") + .HasColumnName("docname"); + + b.Property("DocumentPath") + .HasMaxLength(1024) + .HasColumnType("NVARCHAR2(1024)") + .HasColumnName("docpath"); + + b.Property("DocumentTemplate") + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("doctemplate"); + + b.Property("DocumentType") + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("doctype"); + + b.Property("EventArgs") + .HasMaxLength(8000) + .HasColumnType("NCLOB") + .HasColumnName("args"); + + b.Property("EventType") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("type"); + + b.Property("HandlerId") + .HasColumnType("RAW(16)") + .HasColumnName("handler_id"); + + b.Property("HostUsername") + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("host_user"); + + b.Property("ProjectName") + .HasMaxLength(250) + .HasColumnType("NVARCHAR2(250)") + .HasColumnName("projectname"); + + b.Property("ProjectNum") + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("projectnum"); + + b.Property("RevitBuild") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("revitbuild"); + + b.Property("RevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("revit"); + + b.Property("Status") + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("status"); + + b.Property("Timestamp") + .HasColumnType("TIMESTAMP(7) WITH TIME ZONE") + .HasColumnName("timestamp"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("username"); + + b.HasKey("Id"); + + b.ToTable("events"); + }); + + modelBuilder.Entity("Telemetry.Api.Domain.Models.ScriptRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("RAW(16)") + .HasColumnName("_id"); + + b.Property("CloneName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("clone"); + + b.Property("CommandBundle") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("NVARCHAR2(250)") + .HasColumnName("commandbundle"); + + b.Property("CommandExtension") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("NVARCHAR2(250)") + .HasColumnName("commandextension"); + + b.Property("CommandName") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("NVARCHAR2(250)") + .HasColumnName("commandname"); + + b.Property("CommandResults") + .HasMaxLength(8000) + .HasColumnType("NCLOB") + .HasColumnName("commandresults"); + + b.Property("CommandUniqueName") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("NVARCHAR2(500)") + .HasColumnName("commanduniquename"); + + b.Property("DocumentName") + .HasMaxLength(250) + .HasColumnType("NVARCHAR2(250)") + .HasColumnName("docname"); + + b.Property("DocumentPath") + .HasMaxLength(1024) + .HasColumnType("NVARCHAR2(1024)") + .HasColumnName("docpath"); + + b.Property("ExecId") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("exec_id"); + + b.Property("ExecTimestamp") + .HasColumnType("TIMESTAMP(7) WITH TIME ZONE") + .HasColumnName("exec_timestamp"); + + b.Property("HostUsername") + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("host_user"); + + b.Property("IsConfig") + .HasColumnType("BOOLEAN") + .HasColumnName("config"); + + b.Property("IsDebug") + .HasColumnType("BOOLEAN") + .HasColumnName("debug"); + + b.Property("IsExecFromGui") + .HasColumnType("BOOLEAN") + .HasColumnName("from_gui"); + + b.Property("PyRevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("pyrevit"); + + b.Property("ResultCode") + .HasColumnType("NUMBER(10)") + .HasColumnName("resultcode"); + + b.Property("RevitBuild") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("revitbuild"); + + b.Property("RevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("revit"); + + b.Property("ScriptPath") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("NVARCHAR2(1024)") + .HasColumnName("scriptpath"); + + b.Property("SessionId") + .HasColumnType("RAW(16)") + .HasColumnName("sessionid"); + + b.Property("Timestamp") + .HasColumnType("TIMESTAMP(7) WITH TIME ZONE") + .HasColumnName("timestamp"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("username"); + + b.HasKey("Id"); + + b.ToTable("scripts"); + }); + + modelBuilder.Entity("Telemetry.Api.Domain.Models.ScriptRecord", b => + { + b.OwnsOne("Telemetry.Api.Domain.Models.TraceInfo", "Trace", b1 => + { + b1.Property("ScriptRecordId") + .HasColumnType("RAW(16)"); + + b1.Property("Message") + .IsRequired() + .HasMaxLength(8000) + .HasColumnType("NCLOB") + .HasColumnName("message"); + + b1.HasKey("ScriptRecordId"); + + b1.ToTable("scripts"); + + b1.WithOwner() + .HasForeignKey("ScriptRecordId"); + + b1.OwnsOne("Telemetry.Api.Domain.Models.EngineInfo", "Engine", b2 => + { + b2.Property("TraceInfoScriptRecordId") + .HasColumnType("RAW(16)"); + + b2.Property("Configs") + .HasMaxLength(8000) + .HasColumnType("json") + .HasColumnName("configs"); + + b2.PrimitiveCollection("SysPaths") + .HasColumnType("NVARCHAR2(2000)") + .HasColumnName("syspath"); + + b2.Property("Type") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("type"); + + b2.Property("Version") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("version"); + + b2.HasKey("TraceInfoScriptRecordId"); + + b2.ToTable("scripts"); + + b2.WithOwner() + .HasForeignKey("TraceInfoScriptRecordId"); + }); + + b1.Navigation("Engine") + .IsRequired(); + }); + + b.Navigation("Trace") + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Telemetry.Migrations.Oracle/Migrations/20260406123021_InitOracle.cs b/src/Telemetry.Migrations.Oracle/Migrations/20260406123021_InitOracle.cs new file mode 100644 index 0000000..67c341d --- /dev/null +++ b/src/Telemetry.Migrations.Oracle/Migrations/20260406123021_InitOracle.cs @@ -0,0 +1,92 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Telemetry.Migrations.Oracle.Migrations +{ + /// + public partial class InitOracle : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "events", + columns: table => new + { + _id = table.Column(type: "RAW(16)", nullable: false), + handler_id = table.Column(type: "RAW(16)", nullable: false), + type = table.Column(type: "NVARCHAR2(100)", maxLength: 100, nullable: false), + status = table.Column(type: "NVARCHAR2(100)", maxLength: 100, nullable: true), + timestamp = table.Column(type: "TIMESTAMP(7) WITH TIME ZONE", nullable: false), + username = table.Column(type: "NVARCHAR2(100)", maxLength: 100, nullable: false), + host_user = table.Column(type: "NVARCHAR2(100)", maxLength: 100, nullable: true), + revitbuild = table.Column(type: "NVARCHAR2(100)", maxLength: 100, nullable: false), + revit = table.Column(type: "NVARCHAR2(100)", maxLength: 100, nullable: false), + cancelled = table.Column(type: "BOOLEAN", nullable: true), + cancellable = table.Column(type: "BOOLEAN", nullable: true), + docid = table.Column(type: "NUMBER(10)", nullable: false), + doctype = table.Column(type: "NVARCHAR2(100)", maxLength: 100, nullable: true), + doctemplate = table.Column(type: "NVARCHAR2(100)", maxLength: 100, nullable: true), + docname = table.Column(type: "NVARCHAR2(250)", maxLength: 250, nullable: true), + docpath = table.Column(type: "NVARCHAR2(1024)", maxLength: 1024, nullable: true), + projectname = table.Column(type: "NVARCHAR2(250)", maxLength: 250, nullable: true), + projectnum = table.Column(type: "NVARCHAR2(100)", maxLength: 100, nullable: true), + args = table.Column(type: "NCLOB", maxLength: 8000, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_events", x => x._id); + }); + + migrationBuilder.CreateTable( + name: "scripts", + columns: table => new + { + _id = table.Column(type: "RAW(16)", nullable: false), + sessionid = table.Column(type: "RAW(16)", nullable: false), + timestamp = table.Column(type: "TIMESTAMP(7) WITH TIME ZONE", nullable: false), + username = table.Column(type: "NVARCHAR2(100)", maxLength: 100, nullable: false), + host_user = table.Column(type: "NVARCHAR2(100)", maxLength: 100, nullable: true), + revitbuild = table.Column(type: "NVARCHAR2(100)", maxLength: 100, nullable: false), + revit = table.Column(type: "NVARCHAR2(100)", maxLength: 100, nullable: false), + pyrevit = table.Column(type: "NVARCHAR2(100)", maxLength: 100, nullable: false), + clone = table.Column(type: "NVARCHAR2(100)", maxLength: 100, nullable: false), + debug = table.Column(type: "BOOLEAN", nullable: false), + config = table.Column(type: "BOOLEAN", nullable: false), + from_gui = table.Column(type: "BOOLEAN", nullable: false), + exec_id = table.Column(type: "NVARCHAR2(100)", maxLength: 100, nullable: false), + exec_timestamp = table.Column(type: "TIMESTAMP(7) WITH TIME ZONE", nullable: false), + commandbundle = table.Column(type: "NVARCHAR2(250)", maxLength: 250, nullable: false), + commandextension = table.Column(type: "NVARCHAR2(250)", maxLength: 250, nullable: false), + commandname = table.Column(type: "NVARCHAR2(250)", maxLength: 250, nullable: false), + commanduniquename = table.Column(type: "NVARCHAR2(500)", maxLength: 500, nullable: false), + docname = table.Column(type: "NVARCHAR2(250)", maxLength: 250, nullable: true), + docpath = table.Column(type: "NVARCHAR2(1024)", maxLength: 1024, nullable: true), + resultcode = table.Column(type: "NUMBER(10)", nullable: false), + scriptpath = table.Column(type: "NVARCHAR2(1024)", maxLength: 1024, nullable: false), + message = table.Column(type: "NCLOB", maxLength: 8000, nullable: false), + type = table.Column(type: "NVARCHAR2(100)", maxLength: 100, nullable: false), + version = table.Column(type: "NVARCHAR2(100)", maxLength: 100, nullable: false), + syspath = table.Column(type: "NVARCHAR2(2000)", nullable: true), + configs = table.Column(type: "json", maxLength: 8000, nullable: true), + commandresults = table.Column(type: "NCLOB", maxLength: 8000, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_scripts", x => x._id); + }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "events"); + + migrationBuilder.DropTable( + name: "scripts"); + } + } +} diff --git a/src/Telemetry.Migrations.Oracle/Migrations/ApplicationDbContextModelSnapshot.cs b/src/Telemetry.Migrations.Oracle/Migrations/ApplicationDbContextModelSnapshot.cs new file mode 100644 index 0000000..8077c90 --- /dev/null +++ b/src/Telemetry.Migrations.Oracle/Migrations/ApplicationDbContextModelSnapshot.cs @@ -0,0 +1,316 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Oracle.EntityFrameworkCore.Metadata; +using Telemetry.Api.Infrastructure.Persistence; + +#nullable disable + +namespace Telemetry.Migrations.Oracle.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + partial class ApplicationDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "10.0.5") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + OracleModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Telemetry.Api.Domain.Models.EventRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("RAW(16)") + .HasColumnName("_id"); + + b.Property("Cancellable") + .HasColumnType("BOOLEAN") + .HasColumnName("cancellable"); + + b.Property("Cancelled") + .HasColumnType("BOOLEAN") + .HasColumnName("cancelled"); + + b.Property("DocumentId") + .HasColumnType("NUMBER(10)") + .HasColumnName("docid"); + + b.Property("DocumentName") + .HasMaxLength(250) + .HasColumnType("NVARCHAR2(250)") + .HasColumnName("docname"); + + b.Property("DocumentPath") + .HasMaxLength(1024) + .HasColumnType("NVARCHAR2(1024)") + .HasColumnName("docpath"); + + b.Property("DocumentTemplate") + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("doctemplate"); + + b.Property("DocumentType") + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("doctype"); + + b.Property("EventArgs") + .HasMaxLength(8000) + .HasColumnType("NCLOB") + .HasColumnName("args"); + + b.Property("EventType") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("type"); + + b.Property("HandlerId") + .HasColumnType("RAW(16)") + .HasColumnName("handler_id"); + + b.Property("HostUsername") + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("host_user"); + + b.Property("ProjectName") + .HasMaxLength(250) + .HasColumnType("NVARCHAR2(250)") + .HasColumnName("projectname"); + + b.Property("ProjectNum") + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("projectnum"); + + b.Property("RevitBuild") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("revitbuild"); + + b.Property("RevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("revit"); + + b.Property("Status") + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("status"); + + b.Property("Timestamp") + .HasColumnType("TIMESTAMP(7) WITH TIME ZONE") + .HasColumnName("timestamp"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("username"); + + b.HasKey("Id"); + + b.ToTable("events"); + }); + + modelBuilder.Entity("Telemetry.Api.Domain.Models.ScriptRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("RAW(16)") + .HasColumnName("_id"); + + b.Property("CloneName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("clone"); + + b.Property("CommandBundle") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("NVARCHAR2(250)") + .HasColumnName("commandbundle"); + + b.Property("CommandExtension") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("NVARCHAR2(250)") + .HasColumnName("commandextension"); + + b.Property("CommandName") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("NVARCHAR2(250)") + .HasColumnName("commandname"); + + b.Property("CommandResults") + .HasMaxLength(8000) + .HasColumnType("NCLOB") + .HasColumnName("commandresults"); + + b.Property("CommandUniqueName") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("NVARCHAR2(500)") + .HasColumnName("commanduniquename"); + + b.Property("DocumentName") + .HasMaxLength(250) + .HasColumnType("NVARCHAR2(250)") + .HasColumnName("docname"); + + b.Property("DocumentPath") + .HasMaxLength(1024) + .HasColumnType("NVARCHAR2(1024)") + .HasColumnName("docpath"); + + b.Property("ExecId") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("exec_id"); + + b.Property("ExecTimestamp") + .HasColumnType("TIMESTAMP(7) WITH TIME ZONE") + .HasColumnName("exec_timestamp"); + + b.Property("HostUsername") + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("host_user"); + + b.Property("IsConfig") + .HasColumnType("BOOLEAN") + .HasColumnName("config"); + + b.Property("IsDebug") + .HasColumnType("BOOLEAN") + .HasColumnName("debug"); + + b.Property("IsExecFromGui") + .HasColumnType("BOOLEAN") + .HasColumnName("from_gui"); + + b.Property("PyRevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("pyrevit"); + + b.Property("ResultCode") + .HasColumnType("NUMBER(10)") + .HasColumnName("resultcode"); + + b.Property("RevitBuild") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("revitbuild"); + + b.Property("RevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("revit"); + + b.Property("ScriptPath") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("NVARCHAR2(1024)") + .HasColumnName("scriptpath"); + + b.Property("SessionId") + .HasColumnType("RAW(16)") + .HasColumnName("sessionid"); + + b.Property("Timestamp") + .HasColumnType("TIMESTAMP(7) WITH TIME ZONE") + .HasColumnName("timestamp"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("username"); + + b.HasKey("Id"); + + b.ToTable("scripts"); + }); + + modelBuilder.Entity("Telemetry.Api.Domain.Models.ScriptRecord", b => + { + b.OwnsOne("Telemetry.Api.Domain.Models.TraceInfo", "Trace", b1 => + { + b1.Property("ScriptRecordId") + .HasColumnType("RAW(16)"); + + b1.Property("Message") + .IsRequired() + .HasMaxLength(8000) + .HasColumnType("NCLOB") + .HasColumnName("message"); + + b1.HasKey("ScriptRecordId"); + + b1.ToTable("scripts"); + + b1.WithOwner() + .HasForeignKey("ScriptRecordId"); + + b1.OwnsOne("Telemetry.Api.Domain.Models.EngineInfo", "Engine", b2 => + { + b2.Property("TraceInfoScriptRecordId") + .HasColumnType("RAW(16)"); + + b2.Property("Configs") + .HasMaxLength(8000) + .HasColumnType("json") + .HasColumnName("configs"); + + b2.PrimitiveCollection("SysPaths") + .HasColumnType("NVARCHAR2(2000)") + .HasColumnName("syspath"); + + b2.Property("Type") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("type"); + + b2.Property("Version") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)") + .HasColumnName("version"); + + b2.HasKey("TraceInfoScriptRecordId"); + + b2.ToTable("scripts"); + + b2.WithOwner() + .HasForeignKey("TraceInfoScriptRecordId"); + }); + + b1.Navigation("Engine") + .IsRequired(); + }); + + b.Navigation("Trace") + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Telemetry.Migrations.Postgres/Migrations/20260406123028_InitPostgres.Designer.cs b/src/Telemetry.Migrations.Postgres/Migrations/20260406123028_InitPostgres.Designer.cs new file mode 100644 index 0000000..6d6affd --- /dev/null +++ b/src/Telemetry.Migrations.Postgres/Migrations/20260406123028_InitPostgres.Designer.cs @@ -0,0 +1,319 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using Telemetry.Api.Infrastructure.Persistence; + +#nullable disable + +namespace Telemetry.Migrations.Postgres.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20260406123028_InitPostgres")] + partial class InitPostgres + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "10.0.5") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Telemetry.Api.Domain.Models.EventRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("_id"); + + b.Property("Cancellable") + .HasColumnType("boolean") + .HasColumnName("cancellable"); + + b.Property("Cancelled") + .HasColumnType("boolean") + .HasColumnName("cancelled"); + + b.Property("DocumentId") + .HasColumnType("integer") + .HasColumnName("docid"); + + b.Property("DocumentName") + .HasMaxLength(250) + .HasColumnType("character varying(250)") + .HasColumnName("docname"); + + b.Property("DocumentPath") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("docpath"); + + b.Property("DocumentTemplate") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("doctemplate"); + + b.Property("DocumentType") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("doctype"); + + b.Property("EventArgs") + .HasMaxLength(8000) + .HasColumnType("character varying(8000)") + .HasColumnName("args"); + + b.Property("EventType") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("type"); + + b.Property("HandlerId") + .HasColumnType("uuid") + .HasColumnName("handler_id"); + + b.Property("HostUsername") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("host_user"); + + b.Property("ProjectName") + .HasMaxLength(250) + .HasColumnType("character varying(250)") + .HasColumnName("projectname"); + + b.Property("ProjectNum") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("projectnum"); + + b.Property("RevitBuild") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("revitbuild"); + + b.Property("RevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("revit"); + + b.Property("Status") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("status"); + + b.Property("Timestamp") + .HasColumnType("timestamp with time zone") + .HasColumnName("timestamp"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("username"); + + b.HasKey("Id"); + + b.ToTable("events"); + }); + + modelBuilder.Entity("Telemetry.Api.Domain.Models.ScriptRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("_id"); + + b.Property("CloneName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("clone"); + + b.Property("CommandBundle") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)") + .HasColumnName("commandbundle"); + + b.Property("CommandExtension") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)") + .HasColumnName("commandextension"); + + b.Property("CommandName") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)") + .HasColumnName("commandname"); + + b.Property("CommandResults") + .HasMaxLength(8000) + .HasColumnType("character varying(8000)") + .HasColumnName("commandresults"); + + b.Property("CommandUniqueName") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("character varying(500)") + .HasColumnName("commanduniquename"); + + b.Property("DocumentName") + .HasMaxLength(250) + .HasColumnType("character varying(250)") + .HasColumnName("docname"); + + b.Property("DocumentPath") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("docpath"); + + b.Property("ExecId") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("exec_id"); + + b.Property("ExecTimestamp") + .HasColumnType("timestamp with time zone") + .HasColumnName("exec_timestamp"); + + b.Property("HostUsername") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("host_user"); + + b.Property("IsConfig") + .HasColumnType("boolean") + .HasColumnName("config"); + + b.Property("IsDebug") + .HasColumnType("boolean") + .HasColumnName("debug"); + + b.Property("IsExecFromGui") + .HasColumnType("boolean") + .HasColumnName("from_gui"); + + b.Property("PyRevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("pyrevit"); + + b.Property("ResultCode") + .HasColumnType("integer") + .HasColumnName("resultcode"); + + b.Property("RevitBuild") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("revitbuild"); + + b.Property("RevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("revit"); + + b.Property("ScriptPath") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("scriptpath"); + + b.Property("SessionId") + .HasColumnType("uuid") + .HasColumnName("sessionid"); + + b.Property("Timestamp") + .HasColumnType("timestamp with time zone") + .HasColumnName("timestamp"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("username"); + + b.HasKey("Id"); + + b.ToTable("scripts"); + }); + + modelBuilder.Entity("Telemetry.Api.Domain.Models.ScriptRecord", b => + { + b.OwnsOne("Telemetry.Api.Domain.Models.TraceInfo", "Trace", b1 => + { + b1.Property("ScriptRecordId") + .HasColumnType("uuid"); + + b1.Property("Message") + .IsRequired() + .HasMaxLength(8000) + .HasColumnType("character varying(8000)") + .HasColumnName("message"); + + b1.HasKey("ScriptRecordId"); + + b1.ToTable("scripts"); + + b1.WithOwner() + .HasForeignKey("ScriptRecordId"); + + b1.OwnsOne("Telemetry.Api.Domain.Models.EngineInfo", "Engine", b2 => + { + b2.Property("TraceInfoScriptRecordId") + .HasColumnType("uuid"); + + b2.Property("Configs") + .HasMaxLength(8000) + .HasColumnType("jsonb") + .HasColumnName("configs"); + + b2.PrimitiveCollection("SysPaths") + .HasColumnType("text[]") + .HasColumnName("syspath"); + + b2.Property("Type") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("type"); + + b2.Property("Version") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("version"); + + b2.HasKey("TraceInfoScriptRecordId"); + + b2.ToTable("scripts"); + + b2.WithOwner() + .HasForeignKey("TraceInfoScriptRecordId"); + }); + + b1.Navigation("Engine") + .IsRequired(); + }); + + b.Navigation("Trace") + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Telemetry.Migrations.Postgres/Migrations/20260406123028_InitPostgres.cs b/src/Telemetry.Migrations.Postgres/Migrations/20260406123028_InitPostgres.cs new file mode 100644 index 0000000..899eb80 --- /dev/null +++ b/src/Telemetry.Migrations.Postgres/Migrations/20260406123028_InitPostgres.cs @@ -0,0 +1,92 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Telemetry.Migrations.Postgres.Migrations +{ + /// + public partial class InitPostgres : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "events", + columns: table => new + { + _id = table.Column(type: "uuid", nullable: false), + handler_id = table.Column(type: "uuid", nullable: false), + type = table.Column(type: "character varying(100)", maxLength: 100, nullable: false), + status = table.Column(type: "character varying(100)", maxLength: 100, nullable: true), + timestamp = table.Column(type: "timestamp with time zone", nullable: false), + username = table.Column(type: "character varying(100)", maxLength: 100, nullable: false), + host_user = table.Column(type: "character varying(100)", maxLength: 100, nullable: true), + revitbuild = table.Column(type: "character varying(100)", maxLength: 100, nullable: false), + revit = table.Column(type: "character varying(100)", maxLength: 100, nullable: false), + cancelled = table.Column(type: "boolean", nullable: true), + cancellable = table.Column(type: "boolean", nullable: true), + docid = table.Column(type: "integer", nullable: false), + doctype = table.Column(type: "character varying(100)", maxLength: 100, nullable: true), + doctemplate = table.Column(type: "character varying(100)", maxLength: 100, nullable: true), + docname = table.Column(type: "character varying(250)", maxLength: 250, nullable: true), + docpath = table.Column(type: "character varying(1024)", maxLength: 1024, nullable: true), + projectname = table.Column(type: "character varying(250)", maxLength: 250, nullable: true), + projectnum = table.Column(type: "character varying(100)", maxLength: 100, nullable: true), + args = table.Column(type: "character varying(8000)", maxLength: 8000, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_events", x => x._id); + }); + + migrationBuilder.CreateTable( + name: "scripts", + columns: table => new + { + _id = table.Column(type: "uuid", nullable: false), + sessionid = table.Column(type: "uuid", nullable: false), + timestamp = table.Column(type: "timestamp with time zone", nullable: false), + username = table.Column(type: "character varying(100)", maxLength: 100, nullable: false), + host_user = table.Column(type: "character varying(100)", maxLength: 100, nullable: true), + revitbuild = table.Column(type: "character varying(100)", maxLength: 100, nullable: false), + revit = table.Column(type: "character varying(100)", maxLength: 100, nullable: false), + pyrevit = table.Column(type: "character varying(100)", maxLength: 100, nullable: false), + clone = table.Column(type: "character varying(100)", maxLength: 100, nullable: false), + debug = table.Column(type: "boolean", nullable: false), + config = table.Column(type: "boolean", nullable: false), + from_gui = table.Column(type: "boolean", nullable: false), + exec_id = table.Column(type: "character varying(100)", maxLength: 100, nullable: false), + exec_timestamp = table.Column(type: "timestamp with time zone", nullable: false), + commandbundle = table.Column(type: "character varying(250)", maxLength: 250, nullable: false), + commandextension = table.Column(type: "character varying(250)", maxLength: 250, nullable: false), + commandname = table.Column(type: "character varying(250)", maxLength: 250, nullable: false), + commanduniquename = table.Column(type: "character varying(500)", maxLength: 500, nullable: false), + docname = table.Column(type: "character varying(250)", maxLength: 250, nullable: true), + docpath = table.Column(type: "character varying(1024)", maxLength: 1024, nullable: true), + resultcode = table.Column(type: "integer", nullable: false), + scriptpath = table.Column(type: "character varying(1024)", maxLength: 1024, nullable: false), + message = table.Column(type: "character varying(8000)", maxLength: 8000, nullable: false), + type = table.Column(type: "character varying(100)", maxLength: 100, nullable: false), + version = table.Column(type: "character varying(100)", maxLength: 100, nullable: false), + syspath = table.Column(type: "text[]", nullable: true), + configs = table.Column(type: "jsonb", maxLength: 8000, nullable: true), + commandresults = table.Column(type: "character varying(8000)", maxLength: 8000, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_scripts", x => x._id); + }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "events"); + + migrationBuilder.DropTable( + name: "scripts"); + } + } +} diff --git a/src/Telemetry.Migrations.Postgres/Migrations/ApplicationDbContextModelSnapshot.cs b/src/Telemetry.Migrations.Postgres/Migrations/ApplicationDbContextModelSnapshot.cs new file mode 100644 index 0000000..c912458 --- /dev/null +++ b/src/Telemetry.Migrations.Postgres/Migrations/ApplicationDbContextModelSnapshot.cs @@ -0,0 +1,316 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using Telemetry.Api.Infrastructure.Persistence; + +#nullable disable + +namespace Telemetry.Migrations.Postgres.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + partial class ApplicationDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "10.0.5") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Telemetry.Api.Domain.Models.EventRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("_id"); + + b.Property("Cancellable") + .HasColumnType("boolean") + .HasColumnName("cancellable"); + + b.Property("Cancelled") + .HasColumnType("boolean") + .HasColumnName("cancelled"); + + b.Property("DocumentId") + .HasColumnType("integer") + .HasColumnName("docid"); + + b.Property("DocumentName") + .HasMaxLength(250) + .HasColumnType("character varying(250)") + .HasColumnName("docname"); + + b.Property("DocumentPath") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("docpath"); + + b.Property("DocumentTemplate") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("doctemplate"); + + b.Property("DocumentType") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("doctype"); + + b.Property("EventArgs") + .HasMaxLength(8000) + .HasColumnType("character varying(8000)") + .HasColumnName("args"); + + b.Property("EventType") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("type"); + + b.Property("HandlerId") + .HasColumnType("uuid") + .HasColumnName("handler_id"); + + b.Property("HostUsername") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("host_user"); + + b.Property("ProjectName") + .HasMaxLength(250) + .HasColumnType("character varying(250)") + .HasColumnName("projectname"); + + b.Property("ProjectNum") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("projectnum"); + + b.Property("RevitBuild") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("revitbuild"); + + b.Property("RevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("revit"); + + b.Property("Status") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("status"); + + b.Property("Timestamp") + .HasColumnType("timestamp with time zone") + .HasColumnName("timestamp"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("username"); + + b.HasKey("Id"); + + b.ToTable("events"); + }); + + modelBuilder.Entity("Telemetry.Api.Domain.Models.ScriptRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("_id"); + + b.Property("CloneName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("clone"); + + b.Property("CommandBundle") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)") + .HasColumnName("commandbundle"); + + b.Property("CommandExtension") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)") + .HasColumnName("commandextension"); + + b.Property("CommandName") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)") + .HasColumnName("commandname"); + + b.Property("CommandResults") + .HasMaxLength(8000) + .HasColumnType("character varying(8000)") + .HasColumnName("commandresults"); + + b.Property("CommandUniqueName") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("character varying(500)") + .HasColumnName("commanduniquename"); + + b.Property("DocumentName") + .HasMaxLength(250) + .HasColumnType("character varying(250)") + .HasColumnName("docname"); + + b.Property("DocumentPath") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("docpath"); + + b.Property("ExecId") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("exec_id"); + + b.Property("ExecTimestamp") + .HasColumnType("timestamp with time zone") + .HasColumnName("exec_timestamp"); + + b.Property("HostUsername") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("host_user"); + + b.Property("IsConfig") + .HasColumnType("boolean") + .HasColumnName("config"); + + b.Property("IsDebug") + .HasColumnType("boolean") + .HasColumnName("debug"); + + b.Property("IsExecFromGui") + .HasColumnType("boolean") + .HasColumnName("from_gui"); + + b.Property("PyRevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("pyrevit"); + + b.Property("ResultCode") + .HasColumnType("integer") + .HasColumnName("resultcode"); + + b.Property("RevitBuild") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("revitbuild"); + + b.Property("RevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("revit"); + + b.Property("ScriptPath") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("scriptpath"); + + b.Property("SessionId") + .HasColumnType("uuid") + .HasColumnName("sessionid"); + + b.Property("Timestamp") + .HasColumnType("timestamp with time zone") + .HasColumnName("timestamp"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("username"); + + b.HasKey("Id"); + + b.ToTable("scripts"); + }); + + modelBuilder.Entity("Telemetry.Api.Domain.Models.ScriptRecord", b => + { + b.OwnsOne("Telemetry.Api.Domain.Models.TraceInfo", "Trace", b1 => + { + b1.Property("ScriptRecordId") + .HasColumnType("uuid"); + + b1.Property("Message") + .IsRequired() + .HasMaxLength(8000) + .HasColumnType("character varying(8000)") + .HasColumnName("message"); + + b1.HasKey("ScriptRecordId"); + + b1.ToTable("scripts"); + + b1.WithOwner() + .HasForeignKey("ScriptRecordId"); + + b1.OwnsOne("Telemetry.Api.Domain.Models.EngineInfo", "Engine", b2 => + { + b2.Property("TraceInfoScriptRecordId") + .HasColumnType("uuid"); + + b2.Property("Configs") + .HasMaxLength(8000) + .HasColumnType("jsonb") + .HasColumnName("configs"); + + b2.PrimitiveCollection("SysPaths") + .HasColumnType("text[]") + .HasColumnName("syspath"); + + b2.Property("Type") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("type"); + + b2.Property("Version") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("version"); + + b2.HasKey("TraceInfoScriptRecordId"); + + b2.ToTable("scripts"); + + b2.WithOwner() + .HasForeignKey("TraceInfoScriptRecordId"); + }); + + b1.Navigation("Engine") + .IsRequired(); + }); + + b.Navigation("Trace") + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Telemetry.Migrations.SqlServer/Migrations/20260406123037_InitSqlServer.Designer.cs b/src/Telemetry.Migrations.SqlServer/Migrations/20260406123037_InitSqlServer.Designer.cs new file mode 100644 index 0000000..269220b --- /dev/null +++ b/src/Telemetry.Migrations.SqlServer/Migrations/20260406123037_InitSqlServer.Designer.cs @@ -0,0 +1,319 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Telemetry.Api.Infrastructure.Persistence; + +#nullable disable + +namespace Telemetry.Migrations.SqlServer.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20260406123037_InitSqlServer")] + partial class InitSqlServer + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "10.0.5") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Telemetry.Api.Domain.Models.EventRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnName("_id"); + + b.Property("Cancellable") + .HasColumnType("bit") + .HasColumnName("cancellable"); + + b.Property("Cancelled") + .HasColumnType("bit") + .HasColumnName("cancelled"); + + b.Property("DocumentId") + .HasColumnType("int") + .HasColumnName("docid"); + + b.Property("DocumentName") + .HasMaxLength(250) + .HasColumnType("nvarchar(250)") + .HasColumnName("docname"); + + b.Property("DocumentPath") + .HasMaxLength(1024) + .HasColumnType("nvarchar(1024)") + .HasColumnName("docpath"); + + b.Property("DocumentTemplate") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("doctemplate"); + + b.Property("DocumentType") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("doctype"); + + b.Property("EventArgs") + .HasMaxLength(8000) + .HasColumnType("nvarchar(max)") + .HasColumnName("args"); + + b.Property("EventType") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("type"); + + b.Property("HandlerId") + .HasColumnType("uniqueidentifier") + .HasColumnName("handler_id"); + + b.Property("HostUsername") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("host_user"); + + b.Property("ProjectName") + .HasMaxLength(250) + .HasColumnType("nvarchar(250)") + .HasColumnName("projectname"); + + b.Property("ProjectNum") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("projectnum"); + + b.Property("RevitBuild") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("revitbuild"); + + b.Property("RevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("revit"); + + b.Property("Status") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("status"); + + b.Property("Timestamp") + .HasColumnType("datetimeoffset") + .HasColumnName("timestamp"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("username"); + + b.HasKey("Id"); + + b.ToTable("events"); + }); + + modelBuilder.Entity("Telemetry.Api.Domain.Models.ScriptRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnName("_id"); + + b.Property("CloneName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("clone"); + + b.Property("CommandBundle") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("nvarchar(250)") + .HasColumnName("commandbundle"); + + b.Property("CommandExtension") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("nvarchar(250)") + .HasColumnName("commandextension"); + + b.Property("CommandName") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("nvarchar(250)") + .HasColumnName("commandname"); + + b.Property("CommandResults") + .HasMaxLength(8000) + .HasColumnType("nvarchar(max)") + .HasColumnName("commandresults"); + + b.Property("CommandUniqueName") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("nvarchar(500)") + .HasColumnName("commanduniquename"); + + b.Property("DocumentName") + .HasMaxLength(250) + .HasColumnType("nvarchar(250)") + .HasColumnName("docname"); + + b.Property("DocumentPath") + .HasMaxLength(1024) + .HasColumnType("nvarchar(1024)") + .HasColumnName("docpath"); + + b.Property("ExecId") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("exec_id"); + + b.Property("ExecTimestamp") + .HasColumnType("datetimeoffset") + .HasColumnName("exec_timestamp"); + + b.Property("HostUsername") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("host_user"); + + b.Property("IsConfig") + .HasColumnType("bit") + .HasColumnName("config"); + + b.Property("IsDebug") + .HasColumnType("bit") + .HasColumnName("debug"); + + b.Property("IsExecFromGui") + .HasColumnType("bit") + .HasColumnName("from_gui"); + + b.Property("PyRevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("pyrevit"); + + b.Property("ResultCode") + .HasColumnType("int") + .HasColumnName("resultcode"); + + b.Property("RevitBuild") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("revitbuild"); + + b.Property("RevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("revit"); + + b.Property("ScriptPath") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("nvarchar(1024)") + .HasColumnName("scriptpath"); + + b.Property("SessionId") + .HasColumnType("uniqueidentifier") + .HasColumnName("sessionid"); + + b.Property("Timestamp") + .HasColumnType("datetimeoffset") + .HasColumnName("timestamp"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("username"); + + b.HasKey("Id"); + + b.ToTable("scripts"); + }); + + modelBuilder.Entity("Telemetry.Api.Domain.Models.ScriptRecord", b => + { + b.OwnsOne("Telemetry.Api.Domain.Models.TraceInfo", "Trace", b1 => + { + b1.Property("ScriptRecordId") + .HasColumnType("uniqueidentifier"); + + b1.Property("Message") + .IsRequired() + .HasMaxLength(8000) + .HasColumnType("nvarchar(max)") + .HasColumnName("message"); + + b1.HasKey("ScriptRecordId"); + + b1.ToTable("scripts"); + + b1.WithOwner() + .HasForeignKey("ScriptRecordId"); + + b1.OwnsOne("Telemetry.Api.Domain.Models.EngineInfo", "Engine", b2 => + { + b2.Property("TraceInfoScriptRecordId") + .HasColumnType("uniqueidentifier"); + + b2.Property("Configs") + .HasMaxLength(8000) + .HasColumnType("nvarchar(max)") + .HasColumnName("configs"); + + b2.PrimitiveCollection("SysPaths") + .HasColumnType("nvarchar(max)") + .HasColumnName("syspath"); + + b2.Property("Type") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("type"); + + b2.Property("Version") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("version"); + + b2.HasKey("TraceInfoScriptRecordId"); + + b2.ToTable("scripts"); + + b2.WithOwner() + .HasForeignKey("TraceInfoScriptRecordId"); + }); + + b1.Navigation("Engine") + .IsRequired(); + }); + + b.Navigation("Trace") + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Telemetry.Migrations.SqlServer/Migrations/20260406123037_InitSqlServer.cs b/src/Telemetry.Migrations.SqlServer/Migrations/20260406123037_InitSqlServer.cs new file mode 100644 index 0000000..b4ecaed --- /dev/null +++ b/src/Telemetry.Migrations.SqlServer/Migrations/20260406123037_InitSqlServer.cs @@ -0,0 +1,92 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Telemetry.Migrations.SqlServer.Migrations +{ + /// + public partial class InitSqlServer : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "events", + columns: table => new + { + _id = table.Column(type: "uniqueidentifier", nullable: false), + handler_id = table.Column(type: "uniqueidentifier", nullable: false), + type = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: false), + status = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: true), + timestamp = table.Column(type: "datetimeoffset", nullable: false), + username = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: false), + host_user = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: true), + revitbuild = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: false), + revit = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: false), + cancelled = table.Column(type: "bit", nullable: true), + cancellable = table.Column(type: "bit", nullable: true), + docid = table.Column(type: "int", nullable: false), + doctype = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: true), + doctemplate = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: true), + docname = table.Column(type: "nvarchar(250)", maxLength: 250, nullable: true), + docpath = table.Column(type: "nvarchar(1024)", maxLength: 1024, nullable: true), + projectname = table.Column(type: "nvarchar(250)", maxLength: 250, nullable: true), + projectnum = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: true), + args = table.Column(type: "nvarchar(max)", maxLength: 8000, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_events", x => x._id); + }); + + migrationBuilder.CreateTable( + name: "scripts", + columns: table => new + { + _id = table.Column(type: "uniqueidentifier", nullable: false), + sessionid = table.Column(type: "uniqueidentifier", nullable: false), + timestamp = table.Column(type: "datetimeoffset", nullable: false), + username = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: false), + host_user = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: true), + revitbuild = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: false), + revit = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: false), + pyrevit = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: false), + clone = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: false), + debug = table.Column(type: "bit", nullable: false), + config = table.Column(type: "bit", nullable: false), + from_gui = table.Column(type: "bit", nullable: false), + exec_id = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: false), + exec_timestamp = table.Column(type: "datetimeoffset", nullable: false), + commandbundle = table.Column(type: "nvarchar(250)", maxLength: 250, nullable: false), + commandextension = table.Column(type: "nvarchar(250)", maxLength: 250, nullable: false), + commandname = table.Column(type: "nvarchar(250)", maxLength: 250, nullable: false), + commanduniquename = table.Column(type: "nvarchar(500)", maxLength: 500, nullable: false), + docname = table.Column(type: "nvarchar(250)", maxLength: 250, nullable: true), + docpath = table.Column(type: "nvarchar(1024)", maxLength: 1024, nullable: true), + resultcode = table.Column(type: "int", nullable: false), + scriptpath = table.Column(type: "nvarchar(1024)", maxLength: 1024, nullable: false), + message = table.Column(type: "nvarchar(max)", maxLength: 8000, nullable: false), + type = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: false), + version = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: false), + syspath = table.Column(type: "nvarchar(max)", nullable: true), + configs = table.Column(type: "nvarchar(max)", maxLength: 8000, nullable: true), + commandresults = table.Column(type: "nvarchar(max)", maxLength: 8000, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_scripts", x => x._id); + }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "events"); + + migrationBuilder.DropTable( + name: "scripts"); + } + } +} diff --git a/src/Telemetry.Migrations.SqlServer/Migrations/ApplicationDbContextModelSnapshot.cs b/src/Telemetry.Migrations.SqlServer/Migrations/ApplicationDbContextModelSnapshot.cs new file mode 100644 index 0000000..67fb58f --- /dev/null +++ b/src/Telemetry.Migrations.SqlServer/Migrations/ApplicationDbContextModelSnapshot.cs @@ -0,0 +1,316 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Telemetry.Api.Infrastructure.Persistence; + +#nullable disable + +namespace Telemetry.Migrations.SqlServer.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + partial class ApplicationDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "10.0.5") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Telemetry.Api.Domain.Models.EventRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnName("_id"); + + b.Property("Cancellable") + .HasColumnType("bit") + .HasColumnName("cancellable"); + + b.Property("Cancelled") + .HasColumnType("bit") + .HasColumnName("cancelled"); + + b.Property("DocumentId") + .HasColumnType("int") + .HasColumnName("docid"); + + b.Property("DocumentName") + .HasMaxLength(250) + .HasColumnType("nvarchar(250)") + .HasColumnName("docname"); + + b.Property("DocumentPath") + .HasMaxLength(1024) + .HasColumnType("nvarchar(1024)") + .HasColumnName("docpath"); + + b.Property("DocumentTemplate") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("doctemplate"); + + b.Property("DocumentType") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("doctype"); + + b.Property("EventArgs") + .HasMaxLength(8000) + .HasColumnType("nvarchar(max)") + .HasColumnName("args"); + + b.Property("EventType") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("type"); + + b.Property("HandlerId") + .HasColumnType("uniqueidentifier") + .HasColumnName("handler_id"); + + b.Property("HostUsername") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("host_user"); + + b.Property("ProjectName") + .HasMaxLength(250) + .HasColumnType("nvarchar(250)") + .HasColumnName("projectname"); + + b.Property("ProjectNum") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("projectnum"); + + b.Property("RevitBuild") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("revitbuild"); + + b.Property("RevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("revit"); + + b.Property("Status") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("status"); + + b.Property("Timestamp") + .HasColumnType("datetimeoffset") + .HasColumnName("timestamp"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("username"); + + b.HasKey("Id"); + + b.ToTable("events"); + }); + + modelBuilder.Entity("Telemetry.Api.Domain.Models.ScriptRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnName("_id"); + + b.Property("CloneName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("clone"); + + b.Property("CommandBundle") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("nvarchar(250)") + .HasColumnName("commandbundle"); + + b.Property("CommandExtension") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("nvarchar(250)") + .HasColumnName("commandextension"); + + b.Property("CommandName") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("nvarchar(250)") + .HasColumnName("commandname"); + + b.Property("CommandResults") + .HasMaxLength(8000) + .HasColumnType("nvarchar(max)") + .HasColumnName("commandresults"); + + b.Property("CommandUniqueName") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("nvarchar(500)") + .HasColumnName("commanduniquename"); + + b.Property("DocumentName") + .HasMaxLength(250) + .HasColumnType("nvarchar(250)") + .HasColumnName("docname"); + + b.Property("DocumentPath") + .HasMaxLength(1024) + .HasColumnType("nvarchar(1024)") + .HasColumnName("docpath"); + + b.Property("ExecId") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("exec_id"); + + b.Property("ExecTimestamp") + .HasColumnType("datetimeoffset") + .HasColumnName("exec_timestamp"); + + b.Property("HostUsername") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("host_user"); + + b.Property("IsConfig") + .HasColumnType("bit") + .HasColumnName("config"); + + b.Property("IsDebug") + .HasColumnType("bit") + .HasColumnName("debug"); + + b.Property("IsExecFromGui") + .HasColumnType("bit") + .HasColumnName("from_gui"); + + b.Property("PyRevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("pyrevit"); + + b.Property("ResultCode") + .HasColumnType("int") + .HasColumnName("resultcode"); + + b.Property("RevitBuild") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("revitbuild"); + + b.Property("RevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("revit"); + + b.Property("ScriptPath") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("nvarchar(1024)") + .HasColumnName("scriptpath"); + + b.Property("SessionId") + .HasColumnType("uniqueidentifier") + .HasColumnName("sessionid"); + + b.Property("Timestamp") + .HasColumnType("datetimeoffset") + .HasColumnName("timestamp"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("username"); + + b.HasKey("Id"); + + b.ToTable("scripts"); + }); + + modelBuilder.Entity("Telemetry.Api.Domain.Models.ScriptRecord", b => + { + b.OwnsOne("Telemetry.Api.Domain.Models.TraceInfo", "Trace", b1 => + { + b1.Property("ScriptRecordId") + .HasColumnType("uniqueidentifier"); + + b1.Property("Message") + .IsRequired() + .HasMaxLength(8000) + .HasColumnType("nvarchar(max)") + .HasColumnName("message"); + + b1.HasKey("ScriptRecordId"); + + b1.ToTable("scripts"); + + b1.WithOwner() + .HasForeignKey("ScriptRecordId"); + + b1.OwnsOne("Telemetry.Api.Domain.Models.EngineInfo", "Engine", b2 => + { + b2.Property("TraceInfoScriptRecordId") + .HasColumnType("uniqueidentifier"); + + b2.Property("Configs") + .HasMaxLength(8000) + .HasColumnType("nvarchar(max)") + .HasColumnName("configs"); + + b2.PrimitiveCollection("SysPaths") + .HasColumnType("nvarchar(max)") + .HasColumnName("syspath"); + + b2.Property("Type") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("type"); + + b2.Property("Version") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasColumnName("version"); + + b2.HasKey("TraceInfoScriptRecordId"); + + b2.ToTable("scripts"); + + b2.WithOwner() + .HasForeignKey("TraceInfoScriptRecordId"); + }); + + b1.Navigation("Engine") + .IsRequired(); + }); + + b.Navigation("Trace") + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Telemetry.Migrations.Sqlite/Migrations/20260406123032_InitSqlite.Designer.cs b/src/Telemetry.Migrations.Sqlite/Migrations/20260406123032_InitSqlite.Designer.cs new file mode 100644 index 0000000..2782e8a --- /dev/null +++ b/src/Telemetry.Migrations.Sqlite/Migrations/20260406123032_InitSqlite.Designer.cs @@ -0,0 +1,314 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Telemetry.Api.Infrastructure.Persistence; + +#nullable disable + +namespace Telemetry.Migrations.Sqlite.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20260406123032_InitSqlite")] + partial class InitSqlite + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "10.0.5"); + + modelBuilder.Entity("Telemetry.Api.Domain.Models.EventRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT") + .HasColumnName("_id"); + + b.Property("Cancellable") + .HasColumnType("INTEGER") + .HasColumnName("cancellable"); + + b.Property("Cancelled") + .HasColumnType("INTEGER") + .HasColumnName("cancelled"); + + b.Property("DocumentId") + .HasColumnType("INTEGER") + .HasColumnName("docid"); + + b.Property("DocumentName") + .HasMaxLength(250) + .HasColumnType("TEXT") + .HasColumnName("docname"); + + b.Property("DocumentPath") + .HasMaxLength(1024) + .HasColumnType("TEXT") + .HasColumnName("docpath"); + + b.Property("DocumentTemplate") + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("doctemplate"); + + b.Property("DocumentType") + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("doctype"); + + b.Property("EventArgs") + .HasMaxLength(8000) + .HasColumnType("TEXT") + .HasColumnName("args"); + + b.Property("EventType") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("type"); + + b.Property("HandlerId") + .HasColumnType("TEXT") + .HasColumnName("handler_id"); + + b.Property("HostUsername") + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("host_user"); + + b.Property("ProjectName") + .HasMaxLength(250) + .HasColumnType("TEXT") + .HasColumnName("projectname"); + + b.Property("ProjectNum") + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("projectnum"); + + b.Property("RevitBuild") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("revitbuild"); + + b.Property("RevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("revit"); + + b.Property("Status") + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("status"); + + b.Property("Timestamp") + .HasColumnType("TEXT") + .HasColumnName("timestamp"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("username"); + + b.HasKey("Id"); + + b.ToTable("events"); + }); + + modelBuilder.Entity("Telemetry.Api.Domain.Models.ScriptRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT") + .HasColumnName("_id"); + + b.Property("CloneName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("clone"); + + b.Property("CommandBundle") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("TEXT") + .HasColumnName("commandbundle"); + + b.Property("CommandExtension") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("TEXT") + .HasColumnName("commandextension"); + + b.Property("CommandName") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("TEXT") + .HasColumnName("commandname"); + + b.Property("CommandResults") + .HasMaxLength(8000) + .HasColumnType("TEXT") + .HasColumnName("commandresults"); + + b.Property("CommandUniqueName") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("TEXT") + .HasColumnName("commanduniquename"); + + b.Property("DocumentName") + .HasMaxLength(250) + .HasColumnType("TEXT") + .HasColumnName("docname"); + + b.Property("DocumentPath") + .HasMaxLength(1024) + .HasColumnType("TEXT") + .HasColumnName("docpath"); + + b.Property("ExecId") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("exec_id"); + + b.Property("ExecTimestamp") + .HasColumnType("TEXT") + .HasColumnName("exec_timestamp"); + + b.Property("HostUsername") + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("host_user"); + + b.Property("IsConfig") + .HasColumnType("INTEGER") + .HasColumnName("config"); + + b.Property("IsDebug") + .HasColumnType("INTEGER") + .HasColumnName("debug"); + + b.Property("IsExecFromGui") + .HasColumnType("INTEGER") + .HasColumnName("from_gui"); + + b.Property("PyRevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("pyrevit"); + + b.Property("ResultCode") + .HasColumnType("INTEGER") + .HasColumnName("resultcode"); + + b.Property("RevitBuild") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("revitbuild"); + + b.Property("RevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("revit"); + + b.Property("ScriptPath") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("TEXT") + .HasColumnName("scriptpath"); + + b.Property("SessionId") + .HasColumnType("TEXT") + .HasColumnName("sessionid"); + + b.Property("Timestamp") + .HasColumnType("TEXT") + .HasColumnName("timestamp"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("username"); + + b.HasKey("Id"); + + b.ToTable("scripts"); + }); + + modelBuilder.Entity("Telemetry.Api.Domain.Models.ScriptRecord", b => + { + b.OwnsOne("Telemetry.Api.Domain.Models.TraceInfo", "Trace", b1 => + { + b1.Property("ScriptRecordId") + .HasColumnType("TEXT"); + + b1.Property("Message") + .IsRequired() + .HasMaxLength(8000) + .HasColumnType("TEXT") + .HasColumnName("message"); + + b1.HasKey("ScriptRecordId"); + + b1.ToTable("scripts"); + + b1.WithOwner() + .HasForeignKey("ScriptRecordId"); + + b1.OwnsOne("Telemetry.Api.Domain.Models.EngineInfo", "Engine", b2 => + { + b2.Property("TraceInfoScriptRecordId") + .HasColumnType("TEXT"); + + b2.Property("Configs") + .HasMaxLength(8000) + .HasColumnType("TEXT") + .HasColumnName("configs"); + + b2.PrimitiveCollection("SysPaths") + .HasColumnType("TEXT") + .HasColumnName("syspath"); + + b2.Property("Type") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("type"); + + b2.Property("Version") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("version"); + + b2.HasKey("TraceInfoScriptRecordId"); + + b2.ToTable("scripts"); + + b2.WithOwner() + .HasForeignKey("TraceInfoScriptRecordId"); + }); + + b1.Navigation("Engine") + .IsRequired(); + }); + + b.Navigation("Trace") + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Telemetry.Migrations.Sqlite/Migrations/20260406123032_InitSqlite.cs b/src/Telemetry.Migrations.Sqlite/Migrations/20260406123032_InitSqlite.cs new file mode 100644 index 0000000..d859b42 --- /dev/null +++ b/src/Telemetry.Migrations.Sqlite/Migrations/20260406123032_InitSqlite.cs @@ -0,0 +1,92 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Telemetry.Migrations.Sqlite.Migrations +{ + /// + public partial class InitSqlite : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "events", + columns: table => new + { + _id = table.Column(type: "TEXT", nullable: false), + handler_id = table.Column(type: "TEXT", nullable: false), + type = table.Column(type: "TEXT", maxLength: 100, nullable: false), + status = table.Column(type: "TEXT", maxLength: 100, nullable: true), + timestamp = table.Column(type: "TEXT", nullable: false), + username = table.Column(type: "TEXT", maxLength: 100, nullable: false), + host_user = table.Column(type: "TEXT", maxLength: 100, nullable: true), + revitbuild = table.Column(type: "TEXT", maxLength: 100, nullable: false), + revit = table.Column(type: "TEXT", maxLength: 100, nullable: false), + cancelled = table.Column(type: "INTEGER", nullable: true), + cancellable = table.Column(type: "INTEGER", nullable: true), + docid = table.Column(type: "INTEGER", nullable: false), + doctype = table.Column(type: "TEXT", maxLength: 100, nullable: true), + doctemplate = table.Column(type: "TEXT", maxLength: 100, nullable: true), + docname = table.Column(type: "TEXT", maxLength: 250, nullable: true), + docpath = table.Column(type: "TEXT", maxLength: 1024, nullable: true), + projectname = table.Column(type: "TEXT", maxLength: 250, nullable: true), + projectnum = table.Column(type: "TEXT", maxLength: 100, nullable: true), + args = table.Column(type: "TEXT", maxLength: 8000, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_events", x => x._id); + }); + + migrationBuilder.CreateTable( + name: "scripts", + columns: table => new + { + _id = table.Column(type: "TEXT", nullable: false), + sessionid = table.Column(type: "TEXT", nullable: false), + timestamp = table.Column(type: "TEXT", nullable: false), + username = table.Column(type: "TEXT", maxLength: 100, nullable: false), + host_user = table.Column(type: "TEXT", maxLength: 100, nullable: true), + revitbuild = table.Column(type: "TEXT", maxLength: 100, nullable: false), + revit = table.Column(type: "TEXT", maxLength: 100, nullable: false), + pyrevit = table.Column(type: "TEXT", maxLength: 100, nullable: false), + clone = table.Column(type: "TEXT", maxLength: 100, nullable: false), + debug = table.Column(type: "INTEGER", nullable: false), + config = table.Column(type: "INTEGER", nullable: false), + from_gui = table.Column(type: "INTEGER", nullable: false), + exec_id = table.Column(type: "TEXT", maxLength: 100, nullable: false), + exec_timestamp = table.Column(type: "TEXT", nullable: false), + commandbundle = table.Column(type: "TEXT", maxLength: 250, nullable: false), + commandextension = table.Column(type: "TEXT", maxLength: 250, nullable: false), + commandname = table.Column(type: "TEXT", maxLength: 250, nullable: false), + commanduniquename = table.Column(type: "TEXT", maxLength: 500, nullable: false), + docname = table.Column(type: "TEXT", maxLength: 250, nullable: true), + docpath = table.Column(type: "TEXT", maxLength: 1024, nullable: true), + resultcode = table.Column(type: "INTEGER", nullable: false), + scriptpath = table.Column(type: "TEXT", maxLength: 1024, nullable: false), + message = table.Column(type: "TEXT", maxLength: 8000, nullable: false), + type = table.Column(type: "TEXT", maxLength: 100, nullable: false), + version = table.Column(type: "TEXT", maxLength: 100, nullable: false), + syspath = table.Column(type: "TEXT", nullable: true), + configs = table.Column(type: "TEXT", maxLength: 8000, nullable: true), + commandresults = table.Column(type: "TEXT", maxLength: 8000, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_scripts", x => x._id); + }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "events"); + + migrationBuilder.DropTable( + name: "scripts"); + } + } +} diff --git a/src/Telemetry.Migrations.Sqlite/Migrations/ApplicationDbContextModelSnapshot.cs b/src/Telemetry.Migrations.Sqlite/Migrations/ApplicationDbContextModelSnapshot.cs new file mode 100644 index 0000000..d677c7e --- /dev/null +++ b/src/Telemetry.Migrations.Sqlite/Migrations/ApplicationDbContextModelSnapshot.cs @@ -0,0 +1,311 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Telemetry.Api.Infrastructure.Persistence; + +#nullable disable + +namespace Telemetry.Migrations.Sqlite.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + partial class ApplicationDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "10.0.5"); + + modelBuilder.Entity("Telemetry.Api.Domain.Models.EventRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT") + .HasColumnName("_id"); + + b.Property("Cancellable") + .HasColumnType("INTEGER") + .HasColumnName("cancellable"); + + b.Property("Cancelled") + .HasColumnType("INTEGER") + .HasColumnName("cancelled"); + + b.Property("DocumentId") + .HasColumnType("INTEGER") + .HasColumnName("docid"); + + b.Property("DocumentName") + .HasMaxLength(250) + .HasColumnType("TEXT") + .HasColumnName("docname"); + + b.Property("DocumentPath") + .HasMaxLength(1024) + .HasColumnType("TEXT") + .HasColumnName("docpath"); + + b.Property("DocumentTemplate") + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("doctemplate"); + + b.Property("DocumentType") + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("doctype"); + + b.Property("EventArgs") + .HasMaxLength(8000) + .HasColumnType("TEXT") + .HasColumnName("args"); + + b.Property("EventType") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("type"); + + b.Property("HandlerId") + .HasColumnType("TEXT") + .HasColumnName("handler_id"); + + b.Property("HostUsername") + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("host_user"); + + b.Property("ProjectName") + .HasMaxLength(250) + .HasColumnType("TEXT") + .HasColumnName("projectname"); + + b.Property("ProjectNum") + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("projectnum"); + + b.Property("RevitBuild") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("revitbuild"); + + b.Property("RevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("revit"); + + b.Property("Status") + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("status"); + + b.Property("Timestamp") + .HasColumnType("TEXT") + .HasColumnName("timestamp"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("username"); + + b.HasKey("Id"); + + b.ToTable("events"); + }); + + modelBuilder.Entity("Telemetry.Api.Domain.Models.ScriptRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT") + .HasColumnName("_id"); + + b.Property("CloneName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("clone"); + + b.Property("CommandBundle") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("TEXT") + .HasColumnName("commandbundle"); + + b.Property("CommandExtension") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("TEXT") + .HasColumnName("commandextension"); + + b.Property("CommandName") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("TEXT") + .HasColumnName("commandname"); + + b.Property("CommandResults") + .HasMaxLength(8000) + .HasColumnType("TEXT") + .HasColumnName("commandresults"); + + b.Property("CommandUniqueName") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("TEXT") + .HasColumnName("commanduniquename"); + + b.Property("DocumentName") + .HasMaxLength(250) + .HasColumnType("TEXT") + .HasColumnName("docname"); + + b.Property("DocumentPath") + .HasMaxLength(1024) + .HasColumnType("TEXT") + .HasColumnName("docpath"); + + b.Property("ExecId") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("exec_id"); + + b.Property("ExecTimestamp") + .HasColumnType("TEXT") + .HasColumnName("exec_timestamp"); + + b.Property("HostUsername") + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("host_user"); + + b.Property("IsConfig") + .HasColumnType("INTEGER") + .HasColumnName("config"); + + b.Property("IsDebug") + .HasColumnType("INTEGER") + .HasColumnName("debug"); + + b.Property("IsExecFromGui") + .HasColumnType("INTEGER") + .HasColumnName("from_gui"); + + b.Property("PyRevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("pyrevit"); + + b.Property("ResultCode") + .HasColumnType("INTEGER") + .HasColumnName("resultcode"); + + b.Property("RevitBuild") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("revitbuild"); + + b.Property("RevitVersion") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("revit"); + + b.Property("ScriptPath") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("TEXT") + .HasColumnName("scriptpath"); + + b.Property("SessionId") + .HasColumnType("TEXT") + .HasColumnName("sessionid"); + + b.Property("Timestamp") + .HasColumnType("TEXT") + .HasColumnName("timestamp"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("username"); + + b.HasKey("Id"); + + b.ToTable("scripts"); + }); + + modelBuilder.Entity("Telemetry.Api.Domain.Models.ScriptRecord", b => + { + b.OwnsOne("Telemetry.Api.Domain.Models.TraceInfo", "Trace", b1 => + { + b1.Property("ScriptRecordId") + .HasColumnType("TEXT"); + + b1.Property("Message") + .IsRequired() + .HasMaxLength(8000) + .HasColumnType("TEXT") + .HasColumnName("message"); + + b1.HasKey("ScriptRecordId"); + + b1.ToTable("scripts"); + + b1.WithOwner() + .HasForeignKey("ScriptRecordId"); + + b1.OwnsOne("Telemetry.Api.Domain.Models.EngineInfo", "Engine", b2 => + { + b2.Property("TraceInfoScriptRecordId") + .HasColumnType("TEXT"); + + b2.Property("Configs") + .HasMaxLength(8000) + .HasColumnType("TEXT") + .HasColumnName("configs"); + + b2.PrimitiveCollection("SysPaths") + .HasColumnType("TEXT") + .HasColumnName("syspath"); + + b2.Property("Type") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("type"); + + b2.Property("Version") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT") + .HasColumnName("version"); + + b2.HasKey("TraceInfoScriptRecordId"); + + b2.ToTable("scripts"); + + b2.WithOwner() + .HasForeignKey("TraceInfoScriptRecordId"); + }); + + b1.Navigation("Engine") + .IsRequired(); + }); + + b.Navigation("Trace") + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} From 939c5bbba562199d63985a2666abff92f322c1de Mon Sep 17 00:00:00 2001 From: dosymep Date: Mon, 6 Apr 2026 19:04:35 +0600 Subject: [PATCH 31/31] add MongoDB native support and refactor context to support multiple providers --- .../Interfaces/IApplicationDbContext.cs | 24 ++--- .../Persistence/ApplicationDbContext.cs | 18 ++++ .../Persistence/MongoNativeDbContext.cs | 75 +++++++++++++++ src/Telemetry.Api/Program.cs | 50 +++++++--- .../Web/Controllers/TelemetryController.cs | 4 +- .../MongoDBNativeIntegrationTests.cs | 96 +++++++++++++++++++ .../Controllers/TelemetryControllerTests.cs | 16 ++-- 7 files changed, 241 insertions(+), 42 deletions(-) create mode 100644 src/Telemetry.Api/Infrastructure/Persistence/MongoNativeDbContext.cs create mode 100644 tests/Telemetry.Api.IntegrationTests/MongoDBNativeIntegrationTests.cs diff --git a/src/Telemetry.Api/Application/Interfaces/IApplicationDbContext.cs b/src/Telemetry.Api/Application/Interfaces/IApplicationDbContext.cs index 96bc143..3a00103 100644 --- a/src/Telemetry.Api/Application/Interfaces/IApplicationDbContext.cs +++ b/src/Telemetry.Api/Application/Interfaces/IApplicationDbContext.cs @@ -10,28 +10,16 @@ namespace Telemetry.Api.Application.Interfaces public interface IApplicationDbContext { /// - /// Represents a collection of event records associated with an entity or process. - /// This property is used to store and manage information about specific occurrences - /// or actions that are relevant to the application context. + /// Asynchronously adds a new event record to the database context. /// - /// - /// Event records stored in this property can include details such as timestamps, - /// descriptions, identifiers, and metadata. It is typically used for logging, - /// auditing, or tracking purposes. - /// - DbSet EventRecords { get; } + /// A task that represents the asynchronous add operation. + Task AddEventRecord(EventRecord eventRecord, CancellationToken cancellationToken); /// - /// Stores a collection of script records associated with the application or system context. - /// This property is utilized to manage and organize information related to scripts, - /// their configurations, or execution details. + /// Asynchronously adds a new script record to the database context. /// - /// - /// Script records contained in this property may include data such as script names, - /// execution statuses, parameters, or any related metadata. It is commonly used - /// for monitoring, debugging, or storing script-related information in a structured manner. - /// - DbSet ScriptRecords { get; } + /// A task that represents the asynchronous add operation. + Task AddScriptRecord(ScriptRecord scriptRecord, CancellationToken cancellationToken); /// /// Asynchronously saves all changes made in the current context to the database. diff --git a/src/Telemetry.Api/Infrastructure/Persistence/ApplicationDbContext.cs b/src/Telemetry.Api/Infrastructure/Persistence/ApplicationDbContext.cs index f9d0a80..3b0f632 100644 --- a/src/Telemetry.Api/Infrastructure/Persistence/ApplicationDbContext.cs +++ b/src/Telemetry.Api/Infrastructure/Persistence/ApplicationDbContext.cs @@ -53,6 +53,24 @@ public ApplicationDbContext(DbContextOptions options) : ba /// public DbSet ScriptRecords => Set(); + /// + /// Asynchronously adds a new event record to the database context. + /// + /// A task that represents the asynchronous add operation. + public async Task AddEventRecord(EventRecord eventRecord, CancellationToken cancellationToken) + { + await EventRecords.AddAsync(eventRecord, cancellationToken); + } + + /// + /// Asynchronously adds a new script record to the database context. + /// + /// A task that represents the asynchronous add operation. + public async Task AddScriptRecord(ScriptRecord scriptRecord, CancellationToken cancellationToken) + { + await ScriptRecords.AddAsync(scriptRecord, cancellationToken); + } + /// /// Asynchronously checks whether a successful connection to the database can be established. /// This method verifies connectivity without performing any data manipulation or transactions. diff --git a/src/Telemetry.Api/Infrastructure/Persistence/MongoNativeDbContext.cs b/src/Telemetry.Api/Infrastructure/Persistence/MongoNativeDbContext.cs new file mode 100644 index 0000000..c8d03de --- /dev/null +++ b/src/Telemetry.Api/Infrastructure/Persistence/MongoNativeDbContext.cs @@ -0,0 +1,75 @@ +using MongoDB.Bson; +using MongoDB.Driver; +using System.ComponentModel.DataAnnotations.Schema; +using System.Reflection; +using Telemetry.Api.Application.Interfaces; +using Telemetry.Api.Domain.Models; + +namespace Telemetry.Api.Infrastructure.Persistence +{ + internal sealed class MongoNativeDbContext : IApplicationDbContext + { + private readonly IMongoClient _mongoClient; + private readonly IMongoDatabase _mongoDatabase; + + private readonly IMongoCollection _eventsCollection; + private readonly IMongoCollection _scriptCollection; + + public MongoNativeDbContext(IMongoClient mongoClient, string mongodbName) + { + _mongoClient = mongoClient; + _mongoDatabase = _mongoClient.GetDatabase(mongodbName); + + _eventsCollection = _mongoDatabase.GetCollection(GetCollectionName()); + _scriptCollection = _mongoDatabase.GetCollection(GetCollectionName()); + } + + + private static string GetCollectionName() + { + var table = typeof(T).GetCustomAttribute(); + return table?.Name ?? typeof(T).Name; + } + + public async Task AddEventRecord(EventRecord eventRecord, CancellationToken cancellationToken) + { + await _eventsCollection.InsertOneAsync(eventRecord, new InsertOneOptions(), cancellationToken); + } + + public async Task AddScriptRecord(ScriptRecord scriptRecord, CancellationToken cancellationToken) + { + await _scriptCollection.InsertOneAsync(scriptRecord, new InsertOneOptions(), cancellationToken); + } + + public Task SaveChangesAsync(CancellationToken cancellationToken) + { + return Task.FromResult(0); + } + + public async Task CanConnectAsync(CancellationToken cancellationToken) + { + try + { + await _mongoClient.GetDatabase("admin") + .RunCommandAsync(new BsonDocument("ping", 1), cancellationToken: cancellationToken); + return true; + } + catch + { + return false; + } + } + + public string GetDbProvider() + { + return "MongoDB Native"; + } + + public async Task GetDbVersionAsync(CancellationToken cancellationToken) + { + BsonDocumentCommand command = new(new BsonDocument {{"buildInfo", 1}}); + BsonValue? version = await _mongoDatabase.RunCommandAsync(command, cancellationToken: cancellationToken); + return version["version"].AsString; + } + } +} \ No newline at end of file diff --git a/src/Telemetry.Api/Program.cs b/src/Telemetry.Api/Program.cs index 83905a4..617d0e0 100644 --- a/src/Telemetry.Api/Program.cs +++ b/src/Telemetry.Api/Program.cs @@ -7,6 +7,7 @@ using Telemetry.Api.Application.Services; using Telemetry.Api.Infrastructure.Persistence; using Serilog; +using MongoDB.Driver; using System.Reflection; using System.Runtime.Loader; @@ -22,11 +23,11 @@ builder.Services.AddHttpLogging(logging => { - logging.LoggingFields = HttpLoggingFields.RequestMethod | - HttpLoggingFields.RequestPath | + logging.LoggingFields = HttpLoggingFields.RequestMethod | + HttpLoggingFields.RequestPath | HttpLoggingFields.ResponseStatusCode | HttpLoggingFields.Duration; - + logging.RequestBodyLogLimit = 4096; logging.ResponseBodyLogLimit = 4096; }); @@ -47,42 +48,62 @@ Log.Information("Using Oracle database"); options.UseOracle(connectionString, x => x.MigrationsAssembly("Telemetry.Migrations.Oracle")); - + LoadAssembly(dbProvider, "Telemetry.Migrations.Oracle.dll"); break; case "postgres": Log.Information("Using PostgresSQL database"); options.UseNpgsql(connectionString, x => x.MigrationsAssembly("Telemetry.Migrations.Postgres")); - + LoadAssembly(dbProvider, "Telemetry.Migrations.Postgres.dll"); break; case "sqlite": Log.Information("Using SQLite database"); options.UseSqlite(connectionString, x => x.MigrationsAssembly("Telemetry.Migrations.Sqlite")); - + LoadAssembly(dbProvider, "Telemetry.Migrations.Sqlite.dll"); break; case "mssql": Log.Information("Using MS SQL database"); options.UseSqlServer(connectionString, x => x.MigrationsAssembly("Telemetry.Migrations.SqlServer")); - + LoadAssembly(dbProvider, "Telemetry.Migrations.SqlServer.dll"); break; case "mongodb": Log.Information("Using MongoDB database"); - string mongoDbName = builder.Configuration.GetValue("MongoDbDatabaseName") ?? "telemetry"; + string mongoDbName = builder.Configuration.GetValue("MongoDbDatabaseName") ?? "pyrevit-telemetry"; options.UseMongoDB(connectionString, mongoDbName); - + + break; + case "mongodb_native": break; default: throw new NotSupportedException($"Provider {dbProvider} is not supported."); } }); -builder.Services.AddScoped(provider => provider.GetRequiredService()); +string? dbProviderValue = builder.Configuration.GetValue("DbProvider")?.ToLower(); +if (dbProviderValue?.Equals("mongodb_native") == true) +{ + string? connectionString = builder.Configuration.GetConnectionString("DefaultConnection"); + if (string.IsNullOrEmpty(connectionString)) + { + throw new InvalidOperationException("Missing connection string"); + } + + string mongoDbName = builder.Configuration.GetValue("MongoDbDatabaseName") ?? "pyrevit-telemetry"; + builder.Services.AddSingleton(new MongoClient(connectionString)); + builder.Services.AddScoped(provider => + new MongoNativeDbContext(provider.GetRequiredService(), mongoDbName)); +} +else +{ + builder.Services.AddScoped(provider => provider.GetRequiredService()); +} + builder.Services.AddSingleton(); builder.Services.AddControllers(); @@ -92,7 +113,7 @@ { string basePath = AppContext.BaseDirectory; options.IncludeXmlComments(Path.Combine(basePath, "Telemetry.Api.xml")); - + options.SwaggerDoc("v2", new OpenApiInfo { @@ -118,7 +139,8 @@ options.ReportApiVersions = true; }); -builder.Services.AddVersionedApiExplorer(setup => { +builder.Services.AddVersionedApiExplorer(setup => +{ setup.GroupNameFormat = "'v'VVV"; setup.SubstituteApiVersionInUrl = true; }); @@ -148,8 +170,8 @@ using IServiceScope scope = app.Services.CreateScope(); ApplicationDbContext db = scope.ServiceProvider.GetRequiredService(); - string? dbProvider = builder.Configuration.GetValue("DbProvider")?.ToLower(); - if (dbProvider is not "mongodb") + string? currentDbProvider = builder.Configuration.GetValue("DbProvider")?.ToLower(); + if (currentDbProvider is not "mongodb" && currentDbProvider is not "mongodb_native") { await db.Database.MigrateAsync(); } diff --git a/src/Telemetry.Api/Web/Controllers/TelemetryController.cs b/src/Telemetry.Api/Web/Controllers/TelemetryController.cs index 85ee306..4882498 100644 --- a/src/Telemetry.Api/Web/Controllers/TelemetryController.cs +++ b/src/Telemetry.Api/Web/Controllers/TelemetryController.cs @@ -60,7 +60,7 @@ public async Task PostScript([FromBody] ScriptRecordDto dto) } ScriptRecord record = dto.ToModel(); - _context.ScriptRecords.Add(record); + await _context.AddScriptRecord(record, ct); await _context.SaveChangesAsync(ct); _logger.LogInformation("Script record saved: {ExecId} by {Username}", record.ExecId, record.Username); @@ -105,7 +105,7 @@ public async Task PostEvent([FromBody] EventRecordDto dto) } EventRecord record = dto.ToModel(); - _context.EventRecords.Add(record); + await _context.AddEventRecord(record, ct); await _context.SaveChangesAsync(ct); _logger.LogInformation("Event record saved: {Type} by {Username}", record.EventType, record.Username); diff --git a/tests/Telemetry.Api.IntegrationTests/MongoDBNativeIntegrationTests.cs b/tests/Telemetry.Api.IntegrationTests/MongoDBNativeIntegrationTests.cs new file mode 100644 index 0000000..9895cc8 --- /dev/null +++ b/tests/Telemetry.Api.IntegrationTests/MongoDBNativeIntegrationTests.cs @@ -0,0 +1,96 @@ +using System.Text; +using Telemetry.Api.Application.DTOs; +using Testcontainers.MongoDb; + +namespace Telemetry.Api.IntegrationTests +{ + public class MongoDBNativeIntegrationTests : BaseIntegrationTest + { + private readonly MongoDbContainer _container = new MongoDbBuilder("mongo:8.2") + .Build(); + + protected override string DbProvider => "mongodb_native"; + protected override string ConnectionString => _container.GetConnectionString(); + protected override string MongoDbDatabaseName => "telemetry_test"; + + public override async Task InitializeAsync() + { + await _container.StartAsync(); + await base.InitializeAsync(); + } + + public override async ValueTask DisposeAsync() + { + await base.DisposeAsync(); + await _container.StopAsync(); + await _container.DisposeAsync(); + } + + [Test] + public async Task GetStatus_ReturnsOk() + { + // Act + HttpResponseMessage response = await Client.GetAsync("/api/v2/status"); + + // Assert + response.EnsureSuccessStatusCode(); + string content = await response.Content.ReadAsStringAsync(); + await Assert.That(content).Contains("\"status\":\"pass\""); + await Assert.That(content).Contains("MongoDB Native"); + } + + [Test] + public async Task PostScript_ReturnsOk() + { + // Arrange + ScriptRecordDto dto = CreateSampleScriptDto(); + + // Act + HttpResponseMessage response = await Client.PostAsJsonAsync("/api/v2/scripts", dto); + + // Assert + response.EnsureSuccessStatusCode(); + } + + [Test] + public async Task PostEvent_ReturnsOk() + { + // Arrange + EventRecordDto dto = CreateSampleEventDto(); + + // Act + HttpResponseMessage response = await Client.PostAsJsonAsync("/api/v2/events", dto); + + // Assert + response.EnsureSuccessStatusCode(); + } + + [Test] + public async Task PostRawScript_ReturnsOk() + { + // Arrange + var content = await File.ReadAllTextAsync("assets/script.json"); + var stringContent = new StringContent(content, Encoding.UTF8, "application/json"); + + // Act + HttpResponseMessage response = await Client.PostAsync("/api/v2/scripts", stringContent); + + // Assert + response.EnsureSuccessStatusCode(); + } + + [Test] + public async Task PostRawEvent_ReturnsOk() + { + // Arrange + var content = await File.ReadAllTextAsync("assets/event.json"); + var stringContent = new StringContent(content, Encoding.UTF8, "application/json"); + + // Act + HttpResponseMessage response = await Client.PostAsync("/api/v2/events", stringContent); + + // Assert + response.EnsureSuccessStatusCode(); + } + } +} \ No newline at end of file diff --git a/tests/Telemetry.Api.UnitTests/Web/Controllers/TelemetryControllerTests.cs b/tests/Telemetry.Api.UnitTests/Web/Controllers/TelemetryControllerTests.cs index 0a2a36d..3e9a243 100644 --- a/tests/Telemetry.Api.UnitTests/Web/Controllers/TelemetryControllerTests.cs +++ b/tests/Telemetry.Api.UnitTests/Web/Controllers/TelemetryControllerTests.cs @@ -35,15 +35,15 @@ public async Task PostScript_ShouldReturnOk_WhenSuccessful() { // Arrange ScriptRecordDto dto = CreateValidScriptRecordDto(); - Mock> mockDbSet = new(); - _mockContext.Setup(c => c.ScriptRecords).Returns(mockDbSet.Object); + _mockContext.Setup(c => c.AddScriptRecord(It.IsAny(), It.IsAny())) + .Returns(Task.CompletedTask); // Act IActionResult result = await _controller.PostScript(dto); // Assert await Assert.That(result).IsTypeOf(); - _mockContext.Verify(c => c.ScriptRecords.Add(It.IsAny()), Times.Once); + _mockContext.Verify(c => c.AddScriptRecord(It.IsAny(), It.IsAny()), Times.Once); _mockContext.Verify(c => c.SaveChangesAsync(It.IsAny()), Times.Once); } @@ -52,15 +52,15 @@ public async Task PostEvent_ShouldReturnOk_WhenSuccessful() { // Arrange EventRecordDto dto = CreateValidEventRecordDto(); - Mock> mockDbSet = new(); - _mockContext.Setup(c => c.EventRecords).Returns(mockDbSet.Object); + _mockContext.Setup(c => c.AddEventRecord(It.IsAny(), It.IsAny())) + .Returns(Task.CompletedTask); // Act IActionResult result = await _controller.PostEvent(dto); // Assert await Assert.That(result).IsTypeOf(); - _mockContext.Verify(c => c.EventRecords.Add(It.IsAny()), Times.Once); + _mockContext.Verify(c => c.AddEventRecord(It.IsAny(), It.IsAny()), Times.Once); _mockContext.Verify(c => c.SaveChangesAsync(It.IsAny()), Times.Once); } @@ -93,7 +93,7 @@ private ScriptRecordDto CreateValidScriptRecordDto() return new ScriptRecordDto() { SessionId = Guid.NewGuid(), - Meta = new MetaDto() {SchemaVersion = new Version(2, 0)}, + Meta = new MetaDto() {SchemaVersion = new Version(2, 0, 0)}, Timestamp = DateTimeOffset.Now, Username = "user", HostUsername = "host", @@ -127,7 +127,7 @@ private EventRecordDto CreateValidEventRecordDto() return new EventRecordDto() { HandlerId = Guid.NewGuid(), - Meta = new MetaDto() {SchemaVersion = new Version(2, 0)}, + Meta = new MetaDto() {SchemaVersion = new Version(2, 0, 0)}, EventType = "DocOpened", Status = "Success", Timestamp = DateTimeOffset.Now,