Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Karapace modernization with uvicorn, FastAPI and OpenTelemetry #1039

Merged
merged 94 commits into from
Feb 13, 2025

Conversation

jjaakola-aiven
Copy link
Contributor

About this change - What it does

Karapace modernization to use uvicorn, FastAPI and OpenTelemetry.

Why this way

The replacement of rapu and aiohttp is required for having more feature complete framework. The FastAPI enables the use of community plugins that are easier to integrate.

The new and changed code is reorganized into directories:

  • src/karapace/api - Schema registry FastAPI server and routers
  • src/karapace/core - Schema registry core engine
  • src/karapace/kafka_rest_apis - REST Proxy

Entry points:

  • src/karapace/kafka_rest_apis/__main__.py - REST Proxy main entry point
  • src/karapace/__main__.py - Schema registry main entry point

Improvements to do later

  • The REST Proxy is still using the rapu and aiohttp.
  • Tests are not yet set to correct modules.
  • There are plenty of cleanup and unused code for removal.
  • The REST Proxy should be separated to own high level module from src/karapace/kafka_rest_apis.
  • Document Schema Registry API endpoints, FastAPI provides good tooling for this.

@jjaakola-aiven jjaakola-aiven changed the title Jjaakola aiven fastapi feat: Karapace modernization with uvicorn, FastAPI and OpenTelemetry Feb 12, 2025
jjaakola-aiven and others added 29 commits February 12, 2025 09:26
- we create a standalone module for SR related components

- we use DI to wire together the SR dependencies

- we move the routers to own folder

- we move the config initialization to DI and app startup
Copy link

Coverage report

Click to see where and how coverage changed

FileStatementsMissingCoverageCoverage
(new stmts)
Lines missing
  src/karapace
  __main__.py 6-100
  src/karapace/api
  content_type.py 6-66
  controller.py 80, 83-101, 105, 124-149, 160-180, 195-196, 206-211, 214-216, 226, 236-237, 245, 247, 249, 251, 270-293, 296, 301, 308-320, 329-347, 361-373, 380-381, 390-398, 406-435, 452-482, 491-544, 552-566, 580-604, 612-617, 629, 653-688, 698-786, 803-873, 878, 885-893, 896-899, 902-913, 922-945
  factory.py 6-69
  src/karapace/api/routers
  config.py 37-40, 55, 76-80, 95-104, 120-129
  health.py 6-86
  master_availability.py 6-60
  mode.py 6-53
  subjects.py 6-215
  src/karapace/core
  auth.py 126, 130, 134, 138, 142, 146, 155-158, 209, 221, 239, 288-290, 300
  config.py 32-33, 149, 178-182, 212, 237-245, 273-278, 285-287, 294-296, 301, 307, 311, 315, 320-346, 350-375
  in_memory_database.py
  messaging.py 55, 109
  schema_models.py
  schema_reader.py 205, 223, 251-252, 322, 345, 373-376
  schema_registry.py 84, 122
  serialization.py 299
  utils.py 31, 222
  src/karapace/core/compatibility/jsonschema
  checks.py
  src/karapace/core/coordinator
  schema_coordinator.py 586
  src/karapace/core/protobuf
  encoding_variants.py
  io.py 105, 191, 266, 272
  serialization.py
  src/karapace/core/protobuf/protopace
  protopace.py
  src/karapace/kafka_rest_apis
  __main__.py 6-48
Project Total  

The report is truncated to 25 files out of 130. To see the full report, please visit the workflow summary page.

This report was generated by python-coverage-comment-action

@jjaakola-aiven jjaakola-aiven marked this pull request as ready for review February 12, 2025 12:40
@jjaakola-aiven jjaakola-aiven requested a review from a team as a code owner February 12, 2025 12:40
Copy link
Contributor

@keejon keejon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice 👍. Just saw some comments in code that maybe can be removed as well as one question for the authorizer.

karapace_container = providers.Container(KarapaceContainer)
no_auth_authorizer = providers.Singleton(NoAuthAndAuthz)
http_authorizer = providers.Singleton(HTTPAuthorizer, auth_file=karapace_container.config().registry_authfile)
# http_authorizer = providers.Singleton(HTTPAuthorizer, create_http_authorizer)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should commented out stuff be removed?

set_health_status_tracing_attributes(health_check_span=health_check_span, health_status=health_status)

# if self._auth is not None:
# resp["schema_registry_authfile_timestamp"] = self._auth.authfile_last_modified
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comment ☝️

telemetry_resource: Resource = Provide[TelemetryContainer.telemetry_resource],
) -> None:
LOG.info("Setting OTel meter provider")
# metrics.set_meter_provider(MeterProvider(resource=telemetry_resource, metric_readers=[meter.get_metric_reader()]))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comment ☝️

controller: KarapaceSchemaRegistryController = Depends(Provide[SchemaRegistryContainer.schema_registry_controller]),
) -> CompatibilityLevelResponse:
subject = Subject(unquote_plus(subject))
if authorizer and not authorizer.check_authorization(user, Operation.Read, f"Subject:{subject}"):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we have to check for authorizer here? Shouldn't this be either instance of HTTPAuthorizer or NoAuthAndAuthz?

)


# TODO is this needed? Is this actually the ids/schema/id/schema??
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This TODO intentional?

# controller: KarapaceSchemaRegistryControllerDep,
# ) -> SchemasResponse:
# # TODO retrieve by id only schema
# return await controller.schemas_get()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comment ☝️

# f"{new_config['advertised_protocol']}://{new_config['advertised_hostname']}:{new_config['advertised_port']}"

# set tags if not set
# new_config["tags"]["app"] = "Karapace"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comments ☝️

# env_name,
# )
#
# config[config_name] = parse_env_value(env_val)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comments ☝️

@jlprat
Copy link
Contributor

jlprat commented Feb 13, 2025

As agreed with @jjaakola-aiven, merging this one

@jlprat jlprat merged commit e5e9f4e into main Feb 13, 2025
10 checks passed
@jlprat jlprat deleted the jjaakola-aiven-fastapi branch February 13, 2025 13:59
@eliax1996
Copy link
Contributor

wow amazing! Congrats for the awesome work @jjaakola-aiven

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants