Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
<PackageVersion Include="Amazon.Lambda.SQSEvents" Version="3.0.0" />
<PackageVersion Include="AngleSharp" Version="1.5.1" />
<PackageVersion Include="Aspire.Hosting" Version="13.4.3" />
<PackageVersion Include="Elastic.Transport" Version="0.17.3" />
<PackageVersion Include="MessagePack" Version="2.5.302" />
<PackageVersion Include="Aspire.Hosting.Testing" Version="13.4.3" />
<PackageVersion Include="AWSSDK.Core" Version="4.0.9.7" />
Expand All @@ -51,8 +52,9 @@
<PackageVersion Include="Elastic.Aspire.Hosting.Elasticsearch" Version="9.3.0" />
<PackageVersion Include="Elastic.Clients.Elasticsearch" Version="9.4.2" />
<PackageVersion Include="FakeItEasy" Version="9.0.1" />
<PackageVersion Include="Elastic.Ingest.Elasticsearch" Version="0.50.2" />
<PackageVersion Include="Elastic.Mapping" Version="0.50.2" />
<PackageVersion Include="Elastic.Ingest.Elasticsearch" Version="0.51.0" />
<PackageVersion Include="Elastic.Mapping" Version="0.51.0" />
<PackageVersion Include="Elastic.Transport.VirtualizedCluster" Version="0.17.3" />
<PackageVersion Include="InMemoryLogger" Version="1.0.66" />
<PackageVersion Include="MartinCostello.Logging.XUnit.v3" Version="0.7.1" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="10.0.8" />
Expand Down
2 changes: 2 additions & 0 deletions config/assembler.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ environments:
cookies_win: x
feature_flags:
WEBSITE_SEARCH: true
PAGE_FEEDBACK: true
website_search_url: https://staging-website.elastic.co/search/elastic-website-search.js
edge:
uri: https://d34ipnu52o64md.cloudfront.net
Expand All @@ -35,6 +36,7 @@ environments:
path_prefix: docs
feature_flags:
WEBSITE_SEARCH: true
PAGE_FEEDBACK: true
website_search_url: http://localhost:4078/elastic-website-search.js
preview:
uri: https://docs-v3-preview.elastic.dev
Expand Down
61 changes: 61 additions & 0 deletions docs/development/page-feedback.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
---
navigation_title: Page feedback
---

# Page feedback

The documentation site records page-level reactions and optional comments in the
`page-feedback-v1-{environment}` Elasticsearch index. The API uses the feedback
identifier as the document `_id`, so later comment submissions and reaction
changes replace the same document.

The thumbs-up or thumbs-down selection writes a document with the reaction after
a short debounce, so quickly changing the selection records only the final
choice. The follow-up questionnaire writes the same document again with a
structured reason, the reason-set version, and optional details. Submitting the
questionnaire flushes any pending reaction write first. This keeps abandoned
questionnaires useful while ensuring the richer submission wins.

Reasons are stored as keyword enum values for filtering and aggregation.
`reason_set_version` identifies the questionnaire revision that presented the
option. Display labels may change without changing their stored value. Add a new
enum value when an option's meaning changes, and retain retired values so older
clients and historical documents remain valid.

The current positive reasons are `accurate`, `solvedProblem`,
`easyToUnderstand`, `helpfulExamples`, and `anotherReason`. The current negative
reasons are `inaccurate`, `missingInformation`, `hardToUnderstand`,
`codeSampleErrors`, and `anotherReason`.

## Provision the index

`PageFeedbackMapping` defines the mapping with `Elastic.Mapping` attributes.
During API startup, `PageFeedbackBootstrapService` uses
`Elastic.Ingest.Elasticsearch` to create or update environment-specific
component and index templates. The generated context uses the API assembly
version as its mapping version. Bootstrap skips unchanged mapping hashes and
prevents an older API task from replacing templates installed by a newer task
during a rolling deployment.

The bootstrap service and runtime gateway share one ingest channel. Feedback
upserts use `DirectWriteAsync` and await the bulk item result before the API
responds. They do not use the channel's retry overload because the browser owns
the bounded retry UX. The first successful feedback write creates the concrete
index from the templates.

The generated mapping disables dynamic field mapping. Fields that are not part
of `PageFeedbackDocument` remain unindexed instead of changing the schema.

Bootstrap failures are logged and ignored in `dev` so the local documentation
server can run without Elasticsearch. They prevent startup in `staging`, `edge`,
and `prod`.

Runtime credentials require permission to manage component and index templates,
create the environment's index, and write and delete its documents.

Template updates do not modify existing indices. For a mapping change, increment
the schema version in the index name, deploy the new template, and migrate any
documents that must be retained. Mixed task versions then write to separate
versioned indices during a rolling deployment. The assembly mapping version is
an additional downgrade guard for templates that retain the same schema-versioned
name; it does not replace index versioning.
1 change: 1 addition & 0 deletions docs/development/toc.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
toc:
- file: index.md
- file: changelog-bundle-registry.md
- file: page-feedback.md
- file: essc.md
- folder: ingest
children:
Expand Down
5 changes: 4 additions & 1 deletion src/Elastic.ApiExplorer/Infrastructure/ApiViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,10 @@ public ApiLayoutViewModel CreateGlobalLayoutModel()
CanonicalBaseUrl = BuildContext.CanonicalBaseUrl,
GoogleTagManager = new GoogleTagManagerConfiguration(),
Optimizely = new OptimizelyConfiguration(),
Features = new FeatureFlags([]),
Features = new FeatureFlags([])
{
PageFeedbackEnabled = BuildContext.Configuration.Features.PageFeedbackEnabled
},
StaticFileContentHashProvider = StaticFileContentHashProvider,
BuildType = BuildContext.BuildType,
TocItems = GetTocItems(),
Expand Down
1 change: 1 addition & 0 deletions src/Elastic.ApiExplorer/_Layout.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ else
<input type="checkbox" class="hidden" id="pages-nav-hamburger">
@await RenderBodyAsync()
</article>
@await RenderPartialAsync(_PageFeedback.Create(Model))
Comment thread
Mpdreamz marked this conversation as resolved.
</main>
</div>
@await RenderPartialAsync(_ApiToc.Create(Model.TocItems.ToArray()))
Expand Down
1 change: 1 addition & 0 deletions src/Elastic.Codex/_MarkdownLayout.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
<input type="checkbox" class="hidden" id="pages-nav-hamburger">
@await RenderBodyAsync()
</article>
@await RenderPartialAsync(_PageFeedback.Create(Model))
Comment thread
Mpdreamz marked this conversation as resolved.
@await RenderPartialAsync(_PrevNextNav.Create(Model))
</div>
@await RenderPartialAsync(_TableOfContents.Create(Model))
Expand Down
1 change: 1 addition & 0 deletions src/Elastic.Documentation.Configuration/BuildContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -149,5 +149,6 @@ public void ReloadConfiguration()
: new DocumentationSetFile();
Configuration = new ConfigurationFile(ConfigurationYaml, this, VersionsConfiguration, ProductsConfiguration);
Configuration.Features.DiagnosticsPanelEnabled = previousFeatures.DiagnosticsPanelEnabled;
Configuration.Features.PageFeedbackEnabled = previousFeatures.PageFeedbackEnabled;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,12 @@ public bool DiagnosticsPanelEnabled
set => _featureFlags["diagnostics-panel"] = value;
}

public bool PageFeedbackEnabled
{
get => IsEnabled("page-feedback");
set => _featureFlags["page-feedback"] = value;
}

private bool IsEnabled(string key)
{
var envKey = $"FEATURE_{key.ToUpperInvariant().Replace('-', '_')}";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

<ItemGroup>
<PackageReference Include="DotNet.Glob" />
<PackageReference Include="Elastic.Transport" />
<PackageReference Include="NetEscapades.EnumGenerators" />
<PackageReference Include="Nullean.Argh.Interfaces" />
<PackageReference Include="Nullean.ScopedFileSystem" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,11 @@
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
// See the LICENSE file in the project root for more information

using Elastic.Documentation.Configuration;
using Elastic.Transport;
using Elastic.Transport.Products.Elasticsearch;

namespace Elastic.Markdown.Exporters.Elasticsearch;
namespace Elastic.Documentation.Configuration;

/// <summary>
/// Factory for creating Elasticsearch transport from endpoint configuration.
/// </summary>
public static class ElasticsearchTransportFactory
{
Comment thread
Mpdreamz marked this conversation as resolved.
public static DistributedTransport Create(ElasticsearchEndpoint endpoint)
Expand All @@ -30,10 +26,10 @@ public static DistributedTransport Create(ElasticsearchEndpoint endpoint)
ProxyUsername = endpoint.ProxyUsername,
ServerCertificateValidationCallback = endpoint.DisableSslVerification
? CertificateValidations.AllowAll
: endpoint.Certificate is { } cert
: endpoint.Certificate is { } certificate
? endpoint.CertificateIsNotRoot
? CertificateValidations.AuthorityPartOfChain(cert)
: CertificateValidations.AuthorityIsRoot(cert)
? CertificateValidations.AuthorityPartOfChain(certificate)
: CertificateValidations.AuthorityIsRoot(certificate)
: null
};

Expand Down
Loading
Loading