feat(metrics): add issuer/signing_algorithm tags + destinations metric for Lemur dashboard#334
Closed
evan-datadog wants to merge 13 commits into
Closed
feat(metrics): add issuer/signing_algorithm tags + destinations metric for Lemur dashboard#334evan-datadog wants to merge 13 commits into
evan-datadog wants to merge 13 commits into
Conversation
Enrich lemur.certificates.days_until_expiration with two low-cardinality tags (issuer, signing_algorithm) and emit a new lemur.certificates.by_destination gauge (1 per cert-destination pair) to enable replication of the Issuers, Signing Algorithms, and Destinations panels from the Lemur UI /#!/dashboard. Tag cardinality: issuer ~5-10, signing_algorithm ~3-5 values. Destinations loaded via joinedload to avoid N+1 queries. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com> Workspace: evan-lemur
There was a problem hiding this comment.
Pull request overview
Adds additional certificate metrics/tagging to support reproducing the Lemur /#!/dashboard panels in Datadog, including issuer/signing-algorithm breakdowns and a destinations breakdown.
Changes:
- Adds
issuerandsigning_algorithmtags tocertificates.days_until_expiration. - Emits a new
certificates.by_destinationgauge (1 per cert-destination pair). - Updates the expiration-metrics query to eager-load
Certificate.destinationsto avoid N+1 when emitting destination metrics.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Add check_dcv_expiration Celery task that iterates all registered issuer plugins implementing get_dcv_expiration_data() and emits lemur.dcv.days_until_expiration gauge per domain. - IssuerPlugin base: optional get_dcv_expiration_data() hook (default: []) - DigiCert plugin: first implementation via GET /v2/domain (paginated) - Metric tags: domain, ca, validation_type, org_id - Config: DIGICERT_DCV_CHECK_ENABLED (default True) - Schedule entry added to local/src/lemur.conf.py as commented reference (production schedule goes in k8s-resources chart/config/lemur.conf.py) Other CAs add DCV monitoring by overriding get_dcv_expiration_data() -- no changes to the Celery task required. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Workspace: evan-lemur
|
…n_data Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Workspace: evan-lemur
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Workspace: evan-lemur
Calling check_dcv_expiration.run() bypasses ContextTask.__call__ which requires a real Flask app context; .run() calls the function directly. Adding the app fixture ensures the Flask context is active when lemur.common.celery is first imported by the @patch decorators. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Workspace: evan-lemur
…fix warn - Remove cert_id from certificates.by_destination tags (cardinality) - Default issuer/signing_algorithm to "unknown" when null - Replace deprecated logger.warn with logger.warning Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Workspace: evan-lemur
…V tests DigiCertIssuerPlugin.__init__ accesses current_app.config["DIGICERT_API_KEY"] via __getitem__, not .get(). The previous Mock(side_effect=...) pattern only patched .get(), leaving __getitem__ returning a MagicMock. That MagicMock ended up as the X-DC-DEVKEY session header value, which requests rejects with InvalidHeader when the request is prepared. Switching to a plain dict satisfies .get(), [], and `in` checks alike. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Workspace: evan-lemur
evan-datadog
commented
Jul 9, 2026
…thon 3.12 mock compat service.py: include replaced certificates in expiry metrics query and add has_been_replaced tag so dashboards can distinguish them. test_certificates.py: add test for has_been_replaced tag in metrics. test_dcv_celery.py: use new_callable=MagicMock on current_app patch to avoid Python 3.12 LocalProxy hasattr issue; drop unused app fixture. test_digicert.py: add MagicMock import; use new_callable=MagicMock on DCV test patches for the same Python 3.12 compatibility reason. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Workspace: evan-lemur
- service.py: simplify has_been_replaced to bool(certificate.replaced); add joinedload(Certificate.replaced) to avoid N+1 queries - celery.py: add exc_info=True + capture_exception() to per-plugin and per-entry error paths; re-raise SoftTimeLimitExceeded before Exception in both inner blocks; use datetime.now(timezone.utc) (3.12 compat); remove redundant local 'import datetime' - plugin.py: guard DIGICERT_URL=None with an actionable ValueError - lemur.conf.py: remove dead DIGICERT_DCV_CHECK_INTERVAL constant Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Workspace: evan-lemur
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
maperu
reviewed
Jul 10, 2026
| """ | ||
| query = ( | ||
| database.db.session.query(Certificate) | ||
| .options(selectinload(Certificate.destinations)) |
This was referenced Jul 10, 2026
Author
|
🤖 Splitting this into two independent PRs so the DCV work and the dashboard-metrics work can be reviewed/merged on their own timelines:
Closing this one in favor of those two. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Three related changes on this branch:
1. Metric tag enrichment (
lemur/certificates/service.py)Adds
issuer,signing_algorithm, andhas_been_replacedtags tolemur.certificates.days_until_expiration, and emitslemur.certificates.by_destinationgauge (1 per cert-destination pair).
issuersigning_algorithmhas_been_replacedtruewhen cert has a non-self-referential successor — lets dashboards filter out superseded certs without a separate tag (CLOUDR-2049)lemur.certificates.by_destinationdestinationDashboard (nqu-dbc-mtt) panels:
sum:lemur.certificates.days_until_expiration{*} by {issuer}sum:lemur.certificates.days_until_expiration{*} by {signing_algorithm}sum:lemur.certificates.by_destination{*} by {destination}...{has_been_replaced:false}2. CA-extensible DCV expiry Celery task (RDNA-1000)
Daily
check_dcv_expirationtask discovers CA plugins implementingget_dcv_expiration_data()and emits
lemur.dcv.days_until_expiration. DigiCert is the first implementation.lemur.dcv.days_until_expirationdomain,ca,validation_type,org_idNote: Celery beat schedule entry must be added to k8s-resources
chart/config/lemur.conf.pyseparately.Test plan
new_callable=MagicMock+ plain dict config; Python 3.12LocalProxycompat)has_been_replacedtag validated in unit testlemur.certificates.by_destinationvisible in DD after staging deploycheck_dcv_expirationto beat scheduleTickets: NIT-26-07, RDNA-1000, CLOUDR-2049
Workspace:
evan-lemur🤖 Generated with Claude Code