diff --git a/.github/ISSUE_TEMPLATE/issue_template.md b/.github/ISSUE_TEMPLATE/issue_template.md index 0d8b352294..0985529940 100644 --- a/.github/ISSUE_TEMPLATE/issue_template.md +++ b/.github/ISSUE_TEMPLATE/issue_template.md @@ -13,8 +13,9 @@ assignees: '' - [ ] Report a technical problem with the documentation - [ ] Other -**Tell us about your request.** Provide a summary of the request and all versions that are affected. - +**Tell us about your request.** Provide a summary of the request. +***Version:** List the OpenSearch version to which this issue applies, e.g. 2.14, 2.12--2.14, or all. + **What other resources are available?** Provide links to related issues, POCs, steps for testing, etc. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 7eccae7052..21b6fbfea6 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -4,6 +4,11 @@ _Describe what this change achieves._ ### Issues Resolved _List any issues this PR will resolve, e.g. Closes [...]._ +### Version +_List the OpenSearch version to which this PR applies, e.g. 2.14, 2.12--2.14, or all._ + +### Frontend features +_If you're submitting documentation for an OpenSearch Dashboards feature, add a video that shows how a user will interact with the UI step by step. A voiceover is optional._ ### Checklist - [ ] By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license and subject to the [Developers Certificate of Origin](https://github.com/opensearch-project/OpenSearch/blob/main/CONTRIBUTING.md#developer-certificate-of-origin). diff --git a/.github/vale/styles/OpenSearch/DashSpacing.yml b/.github/vale/styles/OpenSearch/DashSpacing.yml index f14b1f83dd..f63274668c 100644 --- a/.github/vale/styles/OpenSearch/DashSpacing.yml +++ b/.github/vale/styles/OpenSearch/DashSpacing.yml @@ -3,5 +3,7 @@ message: "There should be no spaces around the dash in '%s'." ignorecase: true nonword: true level: error +scope: + - ~list tokens: - '\w+ +-{2,3} +\w+' \ No newline at end of file diff --git a/.github/vale/styles/Vocab/OpenSearch/Products/accept.txt b/.github/vale/styles/Vocab/OpenSearch/Products/accept.txt index 16e7562dcc..83e9aee603 100644 --- a/.github/vale/styles/Vocab/OpenSearch/Products/accept.txt +++ b/.github/vale/styles/Vocab/OpenSearch/Products/accept.txt @@ -8,6 +8,7 @@ Amazon SageMaker Ansible Auditbeat AWS Cloud +Cohere Command Cognito Dashboards Query Language Data Prepper diff --git a/.github/vale/tests/test-style-neg.md b/.github/vale/tests/test-style-neg.md index 4049eec3cb..39bf65f964 100644 --- a/.github/vale/tests/test-style-neg.md +++ b/.github/vale/tests/test-style-neg.md @@ -6,6 +6,10 @@ This sentence tests cybersecurity. This sentence tests dash---spacing. +This sentence tests: + + - Dash --- spacing in a list. + This sentence tests numbers above 1.2 in versions 1.2 and earlier. This sentence tests upper-right and lower left. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f9f1a23f51..de44bbe4ee 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -82,7 +82,7 @@ Follow these steps to set up your local copy of the repository: ``` curl -sSL https://get.rvm.io | bash -s stable - rvm install 3.2 + rvm install 3.2.4 ruby -v ``` diff --git a/STYLE_GUIDE.md b/STYLE_GUIDE.md index d0602c92e1..e33f49697d 100644 --- a/STYLE_GUIDE.md +++ b/STYLE_GUIDE.md @@ -25,16 +25,16 @@ The following naming conventions should be observed in OpenSearch Project conten Capitalize product names. The OpenSearch Project has three products: OpenSearch, OpenSearch Dashboards, and Data Prepper. For example: -* “To install *OpenSearch*, download the Docker image.” -* “To access *OpenSearch Dashboards*, open your browser and navigate to http://localhost:5601/app/home.” -* “*Data Prepper* contains the following components:” +* "To install *OpenSearch*, download the Docker image." +* "To access *OpenSearch Dashboards*, open your browser and navigate to http://localhost:5601/app/home." +* "*Data Prepper* contains the following components:" Capitalize the names of clients and tools. For example: -* “The OpenSearch *Python* client provides a more natural syntax for interacting with your cluster.” -* “The *Go* client retries requests for a maximum of three times by default.” -* “The *OpenSearch Kubernetes Operator* is an open-source Kubernetes operator that helps automate the deployment and provisioning of OpenSearch and OpenSearch Dashboards in a containerized environment.” -* “You can send events to *Logstash* from many different sources.” +* "The OpenSearch *Python* client provides a more natural syntax for interacting with your cluster." +* "The *Go* client retries requests for a maximum of three times by default." +* "The *OpenSearch Kubernetes Operator* is an open-source Kubernetes operator that helps automate the deployment and provisioning of OpenSearch and OpenSearch Dashboards in a containerized environment." +* "You can send events to *Logstash* from many different sources." #### Features @@ -42,17 +42,17 @@ Features are the individual building blocks of user experiences, reflect the fun Use lowercase when referring to features, unless you are referring to a formally named feature that is specific to OpenSearch. For example: -* “The Notifications plugin provides a central location for all of your *notifications* from OpenSearch plugins.” -* “*Remote-backed storage* is an experimental feature. Therefore, we do not recommend the use of *remote-backed storage* in a production environment.” -* “You can take and restore *snapshots* using the snapshot API.” -* “You can use the *VisBuilder* visualization type in OpenSearch Dashboards to create data visualizations by using a drag-and-drop gesture” (You can refer to VisBuilder alone or qualify the term with “visualization type”). +* "The Notifications plugin provides a central location for all of your *notifications* from OpenSearch plugins." +* "*Remote-backed storage* is an experimental feature. Therefore, we do not recommend the use of *remote-backed storage* in a production environment." +* "You can take and restore *snapshots* using the snapshot API." +* "You can use the *VisBuilder* visualization type in OpenSearch Dashboards to create data visualizations by using a drag-and-drop gesture" (You can refer to VisBuilder alone or qualify the term with "visualization type"). #### Plugin names A plugin is a feature or distinct component that extends the functionality of OpenSearch. For now, capitalize plugin names, but use *plugin* sparingly. The concept of plugins will become obsolete once we re-architect the product. For example: -* “Interaction with the *ML Commons* plugin occurs through either the REST API or [ad](https://opensearch.org/docs/latest/search-plugins/sql/ppl/functions#ad) and [kmeans](https://opensearch.org/docs/latest/search-plugins/sql/ppl/functions#kmeans) Piped Processing Language (PPL) commands.” -* “Use the *Neural Search* plugin to integrate ML language models into your search workloads.” +* "Interaction with the *ML Commons* plugin occurs through either the REST API or [ad](https://opensearch.org/docs/latest/search-plugins/sql/ppl/functions#ad) and [kmeans](https://opensearch.org/docs/latest/search-plugins/sql/ppl/functions#kmeans) Piped Processing Language (PPL) commands." +* "Use the *Neural Search* plugin to integrate ML language models into your search workloads." ### Voice and tone @@ -66,9 +66,9 @@ Whenever possible, use the active voice instead of the passive voice. The passiv Refer to the reader as _you_ (second person), and refer to the OpenSearch Project as _we_ (first person). If there are multiple authors for a blog post, you can use _we_ to refer to the authors as individuals. Do not refer to the OpenSearch Project or to the AWS personnel working on the project as a *team*, as this implies differentiation within the community. -In most cases, try to describe the actions that the user takes rather than contextualizing from the feature perspective. For example, use phrases such as “With this feature, you can...” or “Use this feature to...” instead of saying a feature *allows*, *enables*, or *lets* the user do something. +In most cases, try to describe the actions that the user takes rather than contextualizing from the feature perspective. For example, use phrases such as "With this feature, you can..." or "Use this feature to..." instead of saying a feature *allows*, *enables*, or *lets* the user do something. -For procedures or instructions, ensure that action is taken by the user (“Then you can stop the container...”) rather than the writer (“We also have to stop the container...”). Reserve the first-person plural for speaking as the OpenSearch Project, with recommendations, warnings, or explanations. +For procedures or instructions, ensure that action is taken by the user ("Then you can stop the container...") rather than the writer ("We also have to stop the container..."). Reserve the first-person plural for speaking as the OpenSearch Project, with recommendations, warnings, or explanations. In general, use the present tense. Use the future tense only when an event happens later than, not immediately after, the action under discussion. @@ -84,11 +84,11 @@ Avoid excessive words, such as please. Be courteous but not wordy. Extra detail | Personality trait | Description | Guidance | | :--------- | :------- | :------ | -| **Clear and precise** | The OpenSearch Project understands that our community works, develops, and builds in roles and organizations that require precise thinking and thorough documentation. We strive to use precise language—to clearly say what we mean without leaving ideas open to interpretation, to support our assertions with facts and figures, and to provide credible and current (third-party) references where called for.

We communicate in plain, direct language that is easily understood. Complex concepts are introduced in a concise, unambiguous way. High-level content is supported by links to more in-depth or technical content that users can engage with at their convenience. | - Write with clarity and choose words carefully. Think about the audience and how they might interpret your assertions.
- Be specific. Avoid estimates or general claims when exact data can be provided.
- Support claims with data. If something is “faster” or “more accurate,” say how much.
- When citing third-party references, include direct links. | -| **Transparent and open** | As an open-source project, we exchange information with the community in an accessible and transparent manner. We publish our product plans in the open on GitHub, share relevant and timely information related to the project through our forum and/or our blog, and engage in open dialogues related to product and feature development in the public sphere. Anyone can view our roadmap, raise a question or an issue, or participate in our community meetings. | - Tell a complete story. If you’re walking the reader through a solution or sharing news, don’t skip important information.
- Be forthcoming. Communicate time-sensitive news and information in a thorough and timely manner.
- If there’s something the reader needs to know, say it up front. Don’t “bury the lede.” | -| **Collaborative and supportive** | We’re part of a community that is here to help. We aim to be resourceful on behalf of the community and encourage others to do the same. To facilitate an open exchange of ideas, we provide forums through which the community can ask and answer one another’s questions. | - Use conversational language that welcomes and engages the audience. Have a dialogue.
- Invite discussion and feedback. We have several mechanisms for open discussion, including requests for comment (RFCs), a [community forum](https://forum.opensearch.org/), and [community meetings](https://www.meetup.com/OpenSearch/). -| **Trustworthy and personable** | We stay grounded in the facts and the data. We do not overstate what our products are capable of. We demonstrate our knowledge in a humble but authoritative way and reliably deliver what we promise. We provide mechanisms and support that allow the audience to explore our products for themselves, demonstrating that our actions consistently match our words.

We speak to the community in a friendly, welcoming, judgment-free way so that our audience perceives us as being approachable. Our content is people oriented and focused on empowering the user directly. | - Claims and assertions should be grounded in facts and data and supported accordingly.
- Do not exaggerate or overstate. Let the facts and results speak for themselves.
- Encourage the audience to explore our products for themselves. Offer guidance to help them do so.
- Write directly and conversationally. Have a dialogue with your audience. Imagine writing as if you’re speaking directly to the person for whom you’re creating content.
- Write from the community, for the community. Anyone creating or consuming content about OpenSearch is a member of the same group, with shared interest in learning about and building better search and analytics solutions. | -| **Inclusive and accessible** | As an open-source project, the OpenSearch Project is for everyone, and we are inclusive. We value the diversity of backgrounds and perspectives in the OpenSearch community and welcome feedback from any contributor, regardless of their experience level.

We design and create content so that people with disabilities can perceive, navigate, and interact with it. This ensures that our documentation is available and useful for everyone and helps improve the general usability of content.

We understand our community is international and our writing takes that into account. We use plain language that avoids idioms and metaphors that may not be clear to the broader community. | - Use inclusive language to connect with the diverse and global OpenSearch Project audience.
- Be careful with our word choices.
- Avoid [sensitive terms](https://github.com/opensearch-project/documentation-website/blob/main/STYLE_GUIDE.md#sensitive-terms).
- Don't use [offensive terms](https://github.com/opensearch-project/documentation-website/blob/main/STYLE_GUIDE.md#offensive-terms).
- Don't use ableist or sexist language or language that perpetuates racist structures or stereotypes.
- Links: Use link text that adequately describes the target page. For example, use the title of the target page instead of “here” or “this link.” In most cases, a formal cross-reference (the title of the page you’re linking to) is the preferred style because it provides context and helps readers understand where they’re going when they choose the link.
- Images:
  - Add introductory text that provides sufficient context for each image.
  - Add ALT text that describes the image for screen readers.
- Procedures: Not everyone uses a mouse, so use device-independent verbs; for example, use “choose” instead of “click.”
- Location: When you’re describing the location of something else in your content, such as an image or another section, use words such as “preceding,” “previous,” or “following” instead of “above” and “below.” +| **Clear and precise** | The OpenSearch Project understands that our community works, develops, and builds in roles and organizations that require precise thinking and thorough documentation. We strive to use precise language—to clearly say what we mean without leaving ideas open to interpretation, to support our assertions with facts and figures, and to provide credible and current (third-party) references where called for.

We communicate in plain, direct language that is easily understood. Complex concepts are introduced in a concise, unambiguous way. High-level content is supported by links to more in-depth or technical content that users can engage with at their convenience. | - Write with clarity and choose words carefully. Think about the audience and how they might interpret your assertions.
- Be specific. Avoid estimates or general claims when exact data can be provided.
- Support claims with data. If something is "faster" or "more accurate," say how much.
- When citing third-party references, include direct links. | +| **Transparent and open** | As an open-source project, we exchange information with the community in an accessible and transparent manner. We publish our product plans in the open on GitHub, share relevant and timely information related to the project through our forum and/or our blog, and engage in open dialogues related to product and feature development in the public sphere. Anyone can view our roadmap, raise a question or an issue, or participate in our community meetings. | - Tell a complete story. If you're walking the reader through a solution or sharing news, don't skip important information.
- Be forthcoming. Communicate time-sensitive news and information in a thorough and timely manner.
- If there's something the reader needs to know, say it up front. Don't "bury the lede." | +| **Collaborative and supportive** | We're part of a community that is here to help. We aim to be resourceful on behalf of the community and encourage others to do the same. To facilitate an open exchange of ideas, we provide forums through which the community can ask and answer one another's questions. | - Use conversational language that welcomes and engages the audience. Have a dialogue.
- Invite discussion and feedback. We have several mechanisms for open discussion, including requests for comment (RFCs), a [community forum](https://forum.opensearch.org/), and [community meetings](https://www.meetup.com/OpenSearch/). +| **Trustworthy and personable** | We stay grounded in the facts and the data. We do not overstate what our products are capable of. We demonstrate our knowledge in a humble but authoritative way and reliably deliver what we promise. We provide mechanisms and support that allow the audience to explore our products for themselves, demonstrating that our actions consistently match our words.

We speak to the community in a friendly, welcoming, judgment-free way so that our audience perceives us as being approachable. Our content is people oriented and focused on empowering the user directly. | - Claims and assertions should be grounded in facts and data and supported accordingly.
- Do not exaggerate or overstate. Let the facts and results speak for themselves.
- Encourage the audience to explore our products for themselves. Offer guidance to help them do so.
- Write directly and conversationally. Have a dialogue with your audience. Imagine writing as if you're speaking directly to the person for whom you're creating content.
- Write from the community, for the community. Anyone creating or consuming content about OpenSearch is a member of the same group, with shared interest in learning about and building better search and analytics solutions. | +| **Inclusive and accessible** | As an open-source project, the OpenSearch Project is for everyone, and we are inclusive. We value the diversity of backgrounds and perspectives in the OpenSearch community and welcome feedback from any contributor, regardless of their experience level.

We design and create content so that people with disabilities can perceive, navigate, and interact with it. This ensures that our documentation is available and useful for everyone and helps improve the general usability of content.

We understand our community is international and our writing takes that into account. We use plain language that avoids idioms and metaphors that may not be clear to the broader community. | - Use inclusive language to connect with the diverse and global OpenSearch Project audience.
- Be careful with our word choices.
- Avoid [sensitive terms](https://github.com/opensearch-project/documentation-website/blob/main/STYLE_GUIDE.md#sensitive-terms).
- Don't use [offensive terms](https://github.com/opensearch-project/documentation-website/blob/main/STYLE_GUIDE.md#offensive-terms).
- Don't use ableist or sexist language or language that perpetuates racist structures or stereotypes.
- Links: Use link text that adequately describes the target page. For example, use the title of the target page instead of "here" or "this link." In most cases, a formal cross-reference (the title of the page you're linking to) is the preferred style because it provides context and helps readers understand where they're going when they choose the link.
- Images:
  - Add introductory text that provides sufficient context for each image.
  - Add ALT text that describes the image for screen readers.
- Procedures: Not everyone uses a mouse, so use device-independent verbs; for example, use "choose" instead of "click."
- Location: When you're describing the location of something else in your content, such as an image or another section, use words such as "preceding," "previous," or "following" instead of "above" and "below." ## Style guidelines @@ -98,7 +98,7 @@ The following guidelines should be observed in OpenSearch Project content. Spell out acronyms the first time that you use them on a page and follow them with the acronym in parentheses. Use the format `spelled-out term (acronym)`. On subsequent use, use the acronym alone. -Do not capitalize the spelled-out form of an acronym unless the spelled-out form is a proper noun or the community generally capitalizes it. In all cases, our usage should reflect the community’s usage. +Do not capitalize the spelled-out form of an acronym unless the spelled-out form is a proper noun or the community generally capitalizes it. In all cases, our usage should reflect the community's usage. In general, spell out acronyms once on a page. However, you can spell them out more often for clarity. @@ -167,7 +167,7 @@ The following table lists acronyms that you don't need to spell out. Calling out code within a sentence or code block makes it clear to readers which items are code specific. The following is general guidance about using code examples and when to use `code font`: * In Markdown, use single backticks (`` ` ``) for inline code formatting and triple backticks (```` ``` ````) for code blocks. For example, writing `` `discovery.type` `` in Markdown will render as `discovery.type`. A line containing three backticks should be included both before and after an example code block. -* In sentences, use code font for things relating to code, for example, “The `from` and `size` parameters are stateless, so the results are based on the latest available data.” +* In sentences, use code font for things relating to code, for example, "The `from` and `size` parameters are stateless, so the results are based on the latest available data." * Use lead-in sentences to clarify the example. Exception: API examples, for which a caption-style lead-in (heading 4) is sufficient. * Use the phrase *such as* for brief examples within a sentence. * Use language-specific indentation in code examples. @@ -220,7 +220,7 @@ When using lead-in sentences, summarize, clarify, or refer to the example that f #### Referring to a variable or placeholder -When introducing a code or command line example that refers to a variable or placeholder in the example, be direct by including the variable or placeholder name in the text. Surround the variable or placeholder name with angle brackets (`<` and `>`), for example, ``. Don't refer to the variable or placeholder by its color or format because these can change. If variable or placeholder texts have a lot in common and there are several for the user to complete, be direct by including a “template” for the input in the replaceable text. +When introducing a code or command line example that refers to a variable or placeholder in the example, be direct by including the variable or placeholder name in the text. Surround the variable or placeholder name with angle brackets (`<` and `>`), for example, ``. Don't refer to the variable or placeholder by its color or format because these can change. If variable or placeholder texts have a lot in common and there are several for the user to complete, be direct by including a "template" for the input in the replaceable text. In the following example, replace `` with your own information: @@ -247,7 +247,7 @@ When introducing a code or command line example that refers to a variable or pla - Add ALT text that describes the image for screen readers. -- When you’re describing the location of an image, use words such as *preceding*, *previous*, or *following* instead of *above* and *below*. +- When you're describing the location of an image, use words such as *preceding*, *previous*, or *following* instead of *above* and *below*. - Text that introduces an image should be a complete sentence and end with a period, not a colon. @@ -265,17 +265,17 @@ When introducing a code or command line example that refers to a variable or pla ### Lists The following guidelines apply to all list types: -- Make lists parallel in content and structure. Don’t mix single words with phrases, don’t start some phrases with a noun and others with a verb, and don’t mix verb forms. +- Make lists parallel in content and structure. Don't mix single words with phrases, don't start some phrases with a noun and others with a verb, and don't mix verb forms. - Present the items in alphabetical order if the order of items is arbitrary. - Capitalize the first letter of the first word of each list item. -- If the list is simple, you don’t need end punctuation for the list items. +- If the list is simple, you don't need end punctuation for the list items. - If the list has a mixture of phrases and sentences, punctuate each list item. - Punctuate each list item with a period if a list item has more than one sentence. - Punctuate list items consistently. If at least one item in a list requires a period, use a period for all items in that list. - Introductory sentences are required for lists. - Introductory sentences should be complete sentences. - Introductory sentences should end with a colon. -- Don’t use semicolons, commas, or conjunctions (like and or or) at the end of list items. +- Don't use semicolons, commas, or conjunctions (like and or or) at the end of list items. ### Numbers and measurement @@ -330,15 +330,17 @@ We follow a slightly modified version of the _Microsoft Writing Style Guide_ gui ### Punctuation and capitalization +- Use straight quotation marks (") and apostrophes (') instead of curly ones (”, ’). + - Use only one space after a period. -- Use contractions carefully for a more casual tone. Use common contractions. Avoid future tense (I’ll), archaic (‘twas), colloquial (ain’t), or compound (couldn’t’ve) contractions. +- Use contractions carefully for a more casual tone. Use common contractions. Avoid future tense (I'll), archaic ('twas), colloquial (ain't), or compound (couldn't've) contractions. - Use sentence case for titles, headings, and table headers. Titles of standalone documents may use title case. - Use lowercase for nouns and noun phrases that are not proper nouns; for example, *big data*. This style follows the standard rules of American English grammar. -- For plural forms of nouns that end in “s”, form the possessive case by adding only an apostrophe. +- For plural forms of nouns that end in "s", form the possessive case by adding only an apostrophe. - When a colon introduces a list of words, a phrase, or other sentence fragment, the first word following the colon is lowercased unless it is a proper name. When a colon introduces one or more complete sentences, the first word following it is capitalized. When text introduces a table or image, it should be a complete sentence and end with a period, not a colon. @@ -351,9 +353,9 @@ We follow a slightly modified version of the _Microsoft Writing Style Guide_ gui - An en dash (–) is the width of an uppercase N. In ranges, do not include spacing on either side. Use an en dash to indicate ranges in values and dates, separate a bullet heading from the following text in a list, or separate an open compound adjective (two compounds, only one of which is hyphenated) from the word that it modifies. -- Words with prefixes are normally closed (no hyphen), whether they are nouns, verbs, adjectives, or adverbs. Note that some industry terms don’t follow this hyphenation guidance. For example, *Command Line Interface* and *high performance computing* aren’t hyphenated, and *machine learning* isn’t hyphenated when used as an adjective. Other terms are hyphenated to improve readability. Examples include *non-production*, *post-migration*, and *pre-migration*. +- Words with prefixes are normally closed (no hyphen), whether they are nouns, verbs, adjectives, or adverbs. Note that some industry terms don't follow this hyphenation guidance. For example, *Command Line Interface* and *high performance computing* aren't hyphenated, and *machine learning* isn't hyphenated when used as an adjective. Other terms are hyphenated to improve readability. Examples include *non-production*, *post-migration*, and *pre-migration*. -- In general, comparative or superlative modifiers with “more,” “most,” “less,” or “least” don’t require hyphens. Use one only if it’s needed to avoid ambiguity. +- In general, comparative or superlative modifiers with "more," "most," "less," or "least" don't require hyphens. Use one only if it's needed to avoid ambiguity. - The ampersand (&) should never be used in a sentence as a replacement for the word and. An exception to this is in acronyms where the ampersand is commonly used, such as in Operations & Maintenance (O&M). @@ -418,7 +420,7 @@ Follow these basic guidelines when writing UI text. ##### Style -* Keep it short. Users don’t want to read dense text. Remember that UI text can expand by 30% when it’s translated into other languages. +* Keep it short. Users don't want to read dense text. Remember that UI text can expand by 30% when it's translated into other languages. * Keep it simple. Try to use simple sentences (one subject, one verb, one main clause and idea) rather than compound or complex sentences. * Prefer active voice over passive voice. For example, "You can attach up to 10 policies" is active voice, and "Up to 10 policies can be attached" is passive voice. * Use device-agnostic language rather than mouse-specific language. For example, use _choose_ instead of _click_ (exception: use _select_ for checkboxes). @@ -447,9 +449,9 @@ Follow these basic guidelines when writing UI text. * Failure recovery * Migrating from one cluster to another -* Use the serial (Oxford) comma. For example, “issues, bug fixes, and features”, not “issues, bug fixes and features”. -* Don’t use the ampersand (&). -* Avoid Latinisms, such as _e.g._, _i.e._, or _etc._ Instead of _e.g._, use _for example_ or _such as_. Instead of _i.e._, use _that is_ or _specifically_. Generally speaking, _etc._ and its equivalents (such as _and more_ or _and so on_) aren’t necessary. +* Use the serial (Oxford) comma. For example, "issues, bug fixes, and features", not "issues, bug fixes and features". +* Don't use the ampersand (&). +* Avoid Latinisms, such as _e.g._, _i.e._, or _etc._ Instead of _e.g._, use _for example_ or _such as_. Instead of _i.e._, use _that is_ or _specifically_. Generally speaking, _etc._ and its equivalents (such as _and more_ or _and so on_) aren't necessary. ## Special considerations for blog posts @@ -463,7 +465,7 @@ Posts tend to be more personable, unlike technical documentation. Ask questions, **Keep it short.** -Deep topics don’t necessarily require long posts. Shorter, more focused posts are easier for readers to digest. Consider breaking a long post into a series, which can also encourage repeat visitors to the blog channel. +Deep topics don't necessarily require long posts. Shorter, more focused posts are easier for readers to digest. Consider breaking a long post into a series, which can also encourage repeat visitors to the blog channel. **Avoid redundancy.** @@ -483,7 +485,7 @@ Our philosophy is that we positively impact users and our industry as we proacti The following terms may be associated with unconscious racial bias, violence, or politically sensitive topics and should not appear in OpenSearch Project content, if possible. Note that many of these terms are still present but on a path to not being supported. For example, `slave` was removed from the Python programming language in 2018, and the open-source community continues to work toward replacing these terms. -| Don’t use | Guidance/Use instead | +| Don't use | Guidance/Use instead | |----------------|-----------------------------| | abort | Don't use because it has unpleasant associations and is unnecessarily harsh sounding. Use *stop*, *end*, or *cancel* instead. | | black day | blocked day | @@ -497,7 +499,7 @@ The following terms may be associated with unconscious racial bias, violence, or ### Sensitive terms -The following terms may be problematic *in some contexts*. This doesn’t mean that you can’t use these terms—just be mindful of their potential associations when using them, and avoid using them to refer to people. +The following terms may be problematic *in some contexts*. This doesn't mean that you can't use these terms—just be mindful of their potential associations when using them, and avoid using them to refer to people. | Avoid using | Guidance/Use instead | |--------------------------|-------------------------------------| @@ -506,5 +508,5 @@ The following terms may be problematic *in some contexts*. This doesn’t mean t ## Trademark policy -The “OpenSearch” word mark should be used in its exact form and not abbreviated or combined with any other word or words (e.g., “OpenSearch” software rather than “OPNSRCH” or “OpenSearch-ified”). See the [OpenSearch Trademark Policy](https://opensearch.org/trademark-usage.html) for more information. Also refer to the policy and to the [OpenSearch Brand Guidelines](https://opensearch.org/brand.html) for guidance regarding the use of the OpenSearch logo. When using another party’s logo, refer to that party’s trademark guidelines. +The "OpenSearch" word mark should be used in its exact form and not abbreviated or combined with any other word or words (e.g., "OpenSearch" software rather than "OPNSRCH" or "OpenSearch-ified"). See the [OpenSearch Trademark Policy](https://opensearch.org/trademark-usage.html) for more information. Also refer to the policy and to the [OpenSearch Brand Guidelines](https://opensearch.org/brand.html) for guidance regarding the use of the OpenSearch logo. When using another party's logo, refer to that party's trademark guidelines. diff --git a/TERMS.md b/TERMS.md index e12cc171ed..7de56f9275 100644 --- a/TERMS.md +++ b/TERMS.md @@ -1,6 +1,6 @@ # OpenSearch terms -This is how we use our terms, but we’re always open to hearing your suggestions. +This is how we use our terms, but we're always open to hearing your suggestions. ## A @@ -38,7 +38,7 @@ A plugin that notifies you when data from one or more OpenSearch indexes meets c Use allow when the user must have security permissions in order to complete the task. -Avoid using allow to refer to making something possible for the user. Instead, rewrite to focus on what’s important from the user’s point of view. +Avoid using allow to refer to making something possible for the user. Instead, rewrite to focus on what's important from the user's point of view. **allow list** @@ -101,7 +101,7 @@ Use on first appearance. On subsequent appearances, *Signature Version 4* may be **below** -Use only for physical space or screen descriptions, such as “the outlet below the vent,” or “the button below the bar pane.” +Use only for physical space or screen descriptions, such as "the outlet below the vent," or "the button below the bar pane." For orientation within a document, use *following* or *later*. @@ -134,11 +134,11 @@ OpenSearch style: **bottom** -Use only as a general screen reference, such as “scroll to the bottom of the page.” Don’t use for window, page, or pane references to features or controls. Rather, use *lower* instead. For example, you can use the following wording: “Choose the button on the lower left.” +Use only as a general screen reference, such as "scroll to the bottom of the page." Don't use for window, page, or pane references to features or controls. Rather, use *lower* instead. For example, you can use the following wording: "Choose the button on the lower left." **browse** -Use when referring to scanning information or browsing the web. Don’t use when describing how to navigate to a particular item on our site or a computer. Instead, use *see* or *navigate to*. +Use when referring to scanning information or browsing the web. Don't use when describing how to navigate to a particular item on our site or a computer. Instead, use *see* or *navigate to*. **build (n., v.)** @@ -152,7 +152,7 @@ certificate authority **certs, certificates** -Use _certificates_ on first mention. It’s OK to use _certs_ thereafter. +Use _certificates_ on first mention. It's OK to use _certs_ thereafter. **checkbox, checkboxes** @@ -186,13 +186,13 @@ A plugin that replicates indexes, mappings, and metadata from one OpenSearch clu **cyber** -Except when dictated by open standards, use as a prefix in a closed compound: don’t use spaces or hyphens between _cyber_ and the rest of the word. +Except when dictated by open standards, use as a prefix in a closed compound: don't use spaces or hyphens between _cyber_ and the rest of the word. ## D **data** -Use data is, not data are. Don’t use datas. Use pieces of data or equivalent to describe individual items within a set of data. +Use data is, not data are. Don't use datas. Use pieces of data or equivalent to describe individual items within a set of data. **data center** @@ -210,8 +210,8 @@ Two words when used generically, but one word when referring to the VMware produ Use one of the following date formats: -- When a human-readable date format is preferred, spell out the date using the Month D, YYYY format (for example, _October 1, 2022_). Do not use an ordinal number for the day (use _1_, not _1st_). If the context is clear, you can omit the year on subsequent mention. If the specific day isn’t known, use the Month YYYY format (for example, _October 2022_). -- When a numeric, lexicographically sortable date is required, use the YYYY-MM-DD format (for example, _2022-10-01_). Make sure to add a zero (0) in front of a single-digit month and day. This is the ISO 8601 standard date format. Make sure also that you use a hyphen (-) and avoid omitting the year. Doing so avoids the ambiguity that’s caused by the common, locally used formats of MM/DD and DD/MM. +- When a human-readable date format is preferred, spell out the date using the Month D, YYYY format (for example, _October 1, 2022_). Do not use an ordinal number for the day (use _1_, not _1st_). If the context is clear, you can omit the year on subsequent mention. If the specific day isn't known, use the Month YYYY format (for example, _October 2022_). +- When a numeric, lexicographically sortable date is required, use the YYYY-MM-DD format (for example, _2022-10-01_). Make sure to add a zero (0) in front of a single-digit month and day. This is the ISO 8601 standard date format. Make sure also that you use a hyphen (-) and avoid omitting the year. Doing so avoids the ambiguity that's caused by the common, locally used formats of MM/DD and DD/MM. **demilitarized zone (DMZ)** @@ -219,7 +219,7 @@ Avoid using. Use *perimeter network* or *perimeter zone* instead. **deny list** -Use to describe a list of items that aren’t allowed (blocked). Do not use _blacklist_. +Use to describe a list of items that aren't allowed (blocked). Do not use _blacklist_. **disable** @@ -234,7 +234,7 @@ Do not use *disable* to refer to users. **double-click** -Always hyphenated. Don’t use _double click_. +Always hyphenated. Don't use _double click_. **downvote** @@ -242,7 +242,7 @@ Always hyphenated. Don’t use _double click_. **due to** -Don’t use. Use _because of_ instead. +Don't use. Use _because of_ instead. ## E @@ -250,11 +250,11 @@ Don’t use. Use _because of_ instead. Avoid the use of *easy*, *easier*, or *easily* if possible when describing or comparing an OpenSearch Project product, feature, or procedure in technical content. Use of these terms is audience dependent. These terms are potentially misleading or inaccurate and might be perceived as condescending by some technical users. Instead, describe what the user can do. -On documentation landing pages, it’s acceptable to use *easy*, *easier*, or *easily* within the service description only. +On documentation landing pages, it's acceptable to use *easy*, *easier*, or *easily* within the service description only. **effect** -_Effect_ as a noun refers to something that’s caused by something else. _Effect_ as a verb means to bring about. Do not confuse with _affect_. +_Effect_ as a noun refers to something that's caused by something else. _Effect_ as a verb means to bring about. Do not confuse with _affect_. **e.g.** @@ -264,7 +264,7 @@ Avoid. Use _for example_ or _such as_ instead. **email** -Use as a singular noun or adjective to refer to the collective concept, and use _message_ or _mail_ for individual items. Use _send email_ as the verb form. Don’t use the plural form because it’s a collective noun. +Use as a singular noun or adjective to refer to the collective concept, and use _message_ or _mail_ for individual items. Use _send email_ as the verb form. Don't use the plural form because it's a collective noun. **enable** @@ -275,7 +275,7 @@ Use *enable* to describe making a feature or command available. For example: Note that alternatives to *enable*—such as *activate*, *turn on*, or *start*—are acceptable usage where appropriate and may be found in existing documentation. In all cases, use language that corresponds to the language used in the UI, if applicable. -Avoid using *enable* to refer to making something possible for the user. Instead, rewrite to focus on what's important from the user's point of view. For example, “With ABC, you can do XYZ” is a stronger statement than “ABC enables you to XYZ.” Additionally, using a task-based statement is usually more clear than the vague “…enables you to….” +Avoid using *enable* to refer to making something possible for the user. Instead, rewrite to focus on what's important from the user's point of view. For example, "With ABC, you can do XYZ" is a stronger statement than "ABC enables you to XYZ." Additionally, using a task-based statement is usually more clear than the vague "…enables you to…." **enter** @@ -285,7 +285,7 @@ In general, use in preference to _type_ when a user adds text or other input (su Do not use. -Generally speaking, etc. and its equivalents (such as and more or and so on) aren’t necessary. +Generally speaking, etc. and its equivalents (such as and more or and so on) aren't necessary. **execute** @@ -397,7 +397,7 @@ Avoid using. Use *not valid* instead. **IP address** -Don’t abbreviate as _IP only_. +Don't abbreviate as _IP only_. ## J @@ -435,7 +435,7 @@ You _start_ an application but _launch_ an instance, environment, or cluster. **let** -Avoid using _let_ to refer to making something in a service or feature possible for the user. Instead, rewrite to focus on what’s important from the user’s point of view. +Avoid using _let_ to refer to making something in a service or feature possible for the user. Instead, rewrite to focus on what's important from the user's point of view. **leverage** @@ -449,7 +449,7 @@ One word in reference to software. OK to use to call out something for comparison. -As a general rule, if you can replace like with similar to, it’s OK to use like. But, if you can replace _like_ with _such as_, use _such as_. +As a general rule, if you can replace like with similar to, it's OK to use like. But, if you can replace _like_ with _such as_, use _such as_. **LLM** @@ -505,9 +505,9 @@ Avoid. Use _can_ or _might_ instead. **must, shall, should** -_Must_ and _shall_ refer to requirements. If the reader doesn’t follow the instruction, something won’t work right. +_Must_ and _shall_ refer to requirements. If the reader doesn't follow the instruction, something won't work right. -_Should_ is used with recommendations. If the reader doesn’t follow the instruction, it might be harder or slower, but it’ll work. +_Should_ is used with recommendations. If the reader doesn't follow the instruction, it might be harder or slower, but it'll work. ## N @@ -517,7 +517,7 @@ Not navigate _in_. **near real time (n.), near real-time (adj.) (NRT)** -Use _near real time_ as a noun; use near real-time as an adjective. Don’t add a hyphen between _near_ and _real time_ or _real-time_. +Use _near real time_ as a noun; use near real-time as an adjective. Don't add a hyphen between _near_ and _real time_ or _real-time_. Spell out _near real time_ on first mention; _NRT_ can be used on subsequent mentions. @@ -543,7 +543,7 @@ The default visualization tool for data in OpenSearch. On first appearance, use open source (n.), open-source (adj.) -Use _open source_ as a noun (for example, “The code used throughout this tutorial is open source and can be freely modified”). Use _open-source_ as an adjective _(open-source software)_. +Use _open source_ as a noun (for example, "The code used throughout this tutorial is open source and can be freely modified"). Use _open-source_ as an adjective _(open-source software)_. **OpenSearch Playground** @@ -554,9 +554,9 @@ Do not precede with _the_. OpenSearch Playground provides a central location for When referencing operating systems in documentation, follow these guidelines: - In general, if your docs or procedures apply to both Linux and macOS, you can also include Unix. -- Unix and UNIX aren’t the same. UNIX is a trademarked name that’s owned by The Open Group. In most cases, you should use Unix. -- When referring to the Mac operating system, use macOS. Don’t say Mac, Mac OS, or OS X. -- When referring to Windows, it’s not necessary to prefix with Microsoft. +- Unix and UNIX aren't the same. UNIX is a trademarked name that's owned by The Open Group. In most cases, you should use Unix. +- When referring to the Mac operating system, use macOS. Don't say Mac, Mac OS, or OS X. +- When referring to Windows, it's not necessary to prefix with Microsoft. - If you need to reference multiple Unix-like operating systems, you should separate by commas and use the following order: Linux, macOS, or Unix. **or earlier, or later** @@ -567,7 +567,7 @@ OK to use with software versions. **Painless** -The default scripting language for OpenSearch, either used inline or stored for repeat use. Similar to Java’s language specification. +The default scripting language for OpenSearch, either used inline or stored for repeat use. Similar to Java's language specification. **per** @@ -598,7 +598,7 @@ Avoid using except in quoted text. **plugin** -Tools inside of OpenSearch that can be customized to enhance OpenSearch’s functionality. For a list of core plugins, see the [OpenSearch plugin installation]({{site.url}}{{site.baseurl}}/opensearch/install/plugins/) page. Capitalize if it appears as part of the product name in the UI. +Tools inside of OpenSearch that can be customized to enhance OpenSearch's functionality. For a list of core plugins, see the [OpenSearch plugin installation]({{site.url}}{{site.baseurl}}/opensearch/install/plugins/) page. Capitalize if it appears as part of the product name in the UI. **pop-up** @@ -630,7 +630,7 @@ A call used to request information about your data. **real time (n.) real-time (adj.)** -Use with caution; this term can imply a degree of responsiveness or speed that may not be true. When needed, use _real time_ as a noun (for example “The request is sent in real time”). Use _real-time_ as an adjective (“A real-time feed is displayed...”). +Use with caution; this term can imply a degree of responsiveness or speed that may not be true. When needed, use _real time_ as a noun (for example "The request is sent in real time"). Use _real-time_ as an adjective ("A real-time feed is displayed..."). **recall** @@ -672,7 +672,7 @@ The following examples of settings illustrate key-value pairs with a colon separ **set up (v.), setup (n., adj.)** -Use _set up_ as a verb (“To set up a new user...”). Use _setup_ as a noun or adjective (“To begin setup...”). +Use _set up_ as a verb ("To set up a new user..."). Use _setup_ as a noun or adjective ("To begin setup..."). **shard** @@ -684,7 +684,7 @@ Don't use. Both *simple* and *simply* are not neutral in tone and might sound co **since** -Use only to describe time events. Don’t use in place of because. +Use only to describe time events. Don't use in place of *because*. **slave** @@ -702,7 +702,7 @@ You _start_ an application but _launch_ an instance, environment, or cluster. **startup (n.), start up (v.)** -Never hyphenated. Use _startup_ as a noun (for example, “The following startup procedure guides you through...”). Use _start up_ as a verb (“You can start up the instances by...”). +Never hyphenated. Use _startup_ as a noun (for example, "The following startup procedure guides you through..."). Use _start up_ as a verb ("You can start up the instances by..."). **Stochastic Gradient Descent (SGD)** @@ -716,7 +716,7 @@ A numerical statistic that is intended to reflect how important a word is to a d **time out (verb), timeout (noun, adjective)** -Never hyphenate. Use _time out_ as a verb (“The request will time out if the server doesn’t respond”). Use _timeout_ as a noun or adjective (“You can set the timeout interval by entering a number into...”). +Never hyphenate. Use _time out_ as a verb ("The request will time out if the server doesn't respond"). Use _timeout_ as a noun or adjective ("You can set the timeout interval by entering a number into..."). **time frame** @@ -792,7 +792,7 @@ Never _web site_. **while, although, whereas** -Only use _while_ to mean “during an interval of time.” Don’t use it to mean although because it is often ambiguous. _Whereas_ is a better alternative to although in many cases, but it can sound overly formal. +Only use _while_ to mean "during an interval of time." Don't use it to mean although because it is often ambiguous. _Whereas_ is a better alternative to although in many cases, but it can sound overly formal. **white day** @@ -806,9 +806,9 @@ Do not use. Use *allow list* instead. **wish, want, desire, need** -_Wish_ and _desire_ are indirect and nuanced versions of _want_. Don’t use them. Be direct. +_Wish_ and _desire_ are indirect and nuanced versions of _want_. Don't use them. Be direct. -Do not confuse wants with needs. Use the term that’s appropriate to the situation. _Need_ connotes a requirement or obligation, whereas _want_ indicates that you have an intent but still a choice of valid actions. +Do not confuse wants with needs. Use the term that's appropriate to the situation. _Need_ connotes a requirement or obligation, whereas _want_ indicates that you have an intent but still a choice of valid actions. ## Y diff --git a/_about/breaking-changes.md b/_about/breaking-changes.md index 9c0bd5134a..6fb5660f78 100644 --- a/_about/breaking-changes.md +++ b/_about/breaking-changes.md @@ -34,7 +34,7 @@ In OpenSearch 2.0, the Alerting plugin is now integrated with new plugins for No ### Drop support for JDK 8 -A Lucene upgrade forced OpenSearch to drop support for JDK 8. As a consequence, the [Java high-level REST client]({{site.url}}{{site.baseurl}}/clients/java-rest-high-level/) no longer supports JDK 8. Restoring JDK 8 support is currently an `opensearch-java` proposal [#156](https://github.com/opensearch-project/opensearch-java/issues/156) and will require removing OpenSearch core as a dependency from the Java client (issue [#262](https://github.com/opensearch-project/opensearch-java/issues/262)). +A Lucene upgrade forced OpenSearch to drop support for JDK 8. As a consequence, the Java high-level REST client no longer supports JDK 8. Restoring JDK 8 support is currently an `opensearch-java` proposal [#156](https://github.com/opensearch-project/opensearch-java/issues/156) and will require removing OpenSearch core as a dependency from the Java client (issue [#262](https://github.com/opensearch-project/opensearch-java/issues/262)). ## 2.5.0 diff --git a/_about/version-history.md b/_about/version-history.md index e17d388b03..0d6d844951 100644 --- a/_about/version-history.md +++ b/_about/version-history.md @@ -9,6 +9,7 @@ permalink: /version-history/ OpenSearch version | Release highlights | Release date :--- | :--- | :--- +[2.15.0](https://github.com/opensearch-project/opensearch-build/blob/main/release-notes/opensearch-release-notes-2.15.0.md) | Includes parallel ingestion processing, SIMD support for exact search, and the ability to disable doc values for the k-NN field. Adds wildcard and derived field types. Improves performance for single-cardinality aggregations, rolling upgrades to remote-backed clusters, and more metrics for top N queries. For a full list of release highlights, see the Release Notes. | 25 June 2024 [2.14.0](https://github.com/opensearch-project/opensearch-build/blob/main/release-notes/opensearch-release-notes-2.14.0.md) | Includes performance improvements to hybrid search and date histogram queries with multi-range traversal, ML model integration within the Ingest API, semantic cache for LangChain applications, low-level vector query interface for neural sparse queries, and improved k-NN search filtering. Provides an experimental tiered cache feature. For a full list of release highlights, see the Release Notes. | 14 May 2024 [2.13.0](https://github.com/opensearch-project/opensearch-build/blob/main/release-notes/opensearch-release-notes-2.13.0.md) | Makes agents and tools and the OpenSearch Assistant Toolkit generally available. Introduces vector quantization within OpenSearch. Adds LLM guardrails and hybrid search with aggregations. Adds the Bloom filter skipping index for Apache Spark data sources, I/O-based admission control, and the ability to add an alerting cluster that manages all alerting tasks. For a full list of release highlights, see the Release Notes. | 2 April 2024 [2.12.0](https://github.com/opensearch-project/opensearch-build/blob/main/release-notes/opensearch-release-notes-2.12.0.md) | Makes concurrent segment search and conversational search generally available. Provides an experimental OpenSearch Assistant Toolkit, including agents and tools, workflow automation, and OpenSearch Assistant for OpenSearch Dashboards UI. Adds a new match-only text field, query insights to monitor top N queries, and k-NN search on nested fields. For a full list of release highlights, see the Release Notes. | 20 February 2024 @@ -29,6 +30,7 @@ OpenSearch version | Release highlights | Release date [2.0.1](https://github.com/opensearch-project/opensearch-build/blob/main/release-notes/opensearch-release-notes-2.0.1.md) | Includes bug fixes and maintenance updates for Alerting and Anomaly Detection. | 16 June 2022 [2.0.0](https://github.com/opensearch-project/opensearch-build/blob/main/release-notes/opensearch-release-notes-2.0.0.md) | Includes document-level monitors for alerting, OpenSearch Notifications plugins, and Geo Map Tiles in OpenSearch Dashboards. Also adds support for Lucene 9 and bug fixes for all OpenSearch plugins. For a full list of release highlights, see the Release Notes. | 26 May 2022 [2.0.0-rc1](https://github.com/opensearch-project/opensearch-build/blob/main/release-notes/opensearch-release-notes-2.0.0-rc1.md) | The Release Candidate for 2.0.0. This version allows you to preview the upcoming 2.0.0 release before the GA release. The preview release adds document-level alerting, support for Lucene 9, and the ability to use term lookup queries in document level security. | 03 May 2022 +[1.3.17](https://github.com/opensearch-project/opensearch-build/blob/main/release-notes/opensearch-release-notes-1.3.17.md) | Includes maintenance updates for OpenSearch security and OpenSearch Dashboards security. | 06 June 2024 [1.3.16](https://github.com/opensearch-project/opensearch-build/blob/main/release-notes/opensearch-release-notes-1.3.16.md) | Includes bug fixes and maintenance updates for OpenSearch security, index management, performance analyzer, and reporting. | 23 April 2024 [1.3.15](https://github.com/opensearch-project/opensearch-build/blob/main/release-notes/opensearch-release-notes-1.3.15.md) | Includes bug fixes and maintenance updates for cross-cluster replication, SQL, OpenSearch Dashboards reporting, and alerting. | 05 March 2024 [1.3.14](https://github.com/opensearch-project/opensearch-build/blob/main/release-notes/opensearch-release-notes-1.3.14.md) | Includes bug fixes and maintenance updates for OpenSearch security and OpenSearch Dashboards security. | 12 December 2023 diff --git a/_aggregations/bucket/geohex-grid.md b/_aggregations/bucket/geohex-grid.md index de11061055..03fd45e369 100644 --- a/_aggregations/bucket/geohex-grid.md +++ b/_aggregations/bucket/geohex-grid.md @@ -5,6 +5,8 @@ parent: Bucket aggregations grand_parent: Aggregations nav_order: 85 redirect_from: + - /opensearch/geohexgrid-agg/ + - /query-dsl/aggregations/geohexgrid-agg/ - /aggregations/geohexgrid/ - /query-dsl/aggregations/geohexgrid/ - /query-dsl/aggregations/bucket/geohex-grid/ diff --git a/_aggregations/bucket/multi-terms.md b/_aggregations/bucket/multi-terms.md index 6fca528b38..62a4d264e0 100644 --- a/_aggregations/bucket/multi-terms.md +++ b/_aggregations/bucket/multi-terms.md @@ -5,6 +5,7 @@ parent: Bucket aggregations grand_parent: Aggregations nav_order: 130 redirect_from: + - /query-dsl/aggregations/bucket/multi-terms/ - /query-dsl/aggregations/multi-terms/ --- diff --git a/_aggregations/bucket/range.md b/_aggregations/bucket/range.md index 61ec2f6276..f4e19f188d 100644 --- a/_aggregations/bucket/range.md +++ b/_aggregations/bucket/range.md @@ -5,6 +5,7 @@ parent: Bucket aggregations grand_parent: Aggregations nav_order: 150 redirect_from: + - /query-dsl/aggregations/bucket/date-range/ - /query-dsl/aggregations/bucket/range/ --- diff --git a/_aggregations/bucket/sampler.md b/_aggregations/bucket/sampler.md index 28bae47b6d..5411052d45 100644 --- a/_aggregations/bucket/sampler.md +++ b/_aggregations/bucket/sampler.md @@ -4,6 +4,8 @@ title: Sampler parent: Bucket aggregations grand_parent: Aggregations nav_order: 170 +redirect_from: + - /query-dsl/aggregations/bucket/diversified-sampler/ --- # Sampler aggregations diff --git a/_aggregations/bucket/significant-terms.md b/_aggregations/bucket/significant-terms.md index 017e3b7dd8..34a4354a73 100644 --- a/_aggregations/bucket/significant-terms.md +++ b/_aggregations/bucket/significant-terms.md @@ -4,6 +4,8 @@ title: Significant terms parent: Bucket aggregations grand_parent: Aggregations nav_order: 180 +redirect_from: + - /query-dsl/aggregations/bucket/significant-terms/ --- # Significant terms aggregations diff --git a/_aggregations/bucket/significant-text.md b/_aggregations/bucket/significant-text.md index 1c136603d6..6f1c7ebeca 100644 --- a/_aggregations/bucket/significant-text.md +++ b/_aggregations/bucket/significant-text.md @@ -4,6 +4,8 @@ title: Significant text parent: Bucket aggregations grand_parent: Aggregations nav_order: 190 +redirect_from: + - /query-dsl/aggregations/bucket/significant-text/ --- # Significant text aggregations diff --git a/_aggregations/bucket/terms.md b/_aggregations/bucket/terms.md index 072ad42cc2..5d05c328d4 100644 --- a/_aggregations/bucket/terms.md +++ b/_aggregations/bucket/terms.md @@ -4,6 +4,8 @@ title: Terms parent: Bucket aggregations grand_parent: Aggregations nav_order: 200 +redirect_from: + - /query-dsl/aggregations/bucket/terms/ --- # Terms aggregations diff --git a/_aggregations/index.md b/_aggregations/index.md index 1c43799a10..385c7a09d8 100644 --- a/_aggregations/index.md +++ b/_aggregations/index.md @@ -6,6 +6,7 @@ nav_order: 5 nav_exclude: true permalink: /aggregations/ redirect_from: + - /query-dsl/aggregations/aggregations/ - /opensearch/aggregations/ - /query-dsl/aggregations/ - /aggregations/index/ diff --git a/_aggregations/metric/median-absolute-deviation.md b/_aggregations/metric/median-absolute-deviation.md new file mode 100644 index 0000000000..7332d7eb2f --- /dev/null +++ b/_aggregations/metric/median-absolute-deviation.md @@ -0,0 +1,158 @@ +--- +layout: default +title: Median absolute deviation +parent: Metric aggregations +grand_parent: Aggregations +nav_order: 65 +redirect_from: + - /query-dsl/aggregations/metric/median-absolute-deviation/ +--- + +# Median absolute deviation aggregations + +The `median_absolute_deviation` metric is a single-value metric aggregation that returns a median absolute deviation field. Median absolute deviation is a statistical measure of data variability. Because the median absolute deviation measures dispersion from the median, it provides a more robust measure of variability that is less affected by outliers in a dataset. + +Median absolute deviation is calculated as follows:
+median_absolute_deviation = median(|Xi - Median(Xi)|) + +The following example calculates the median absolute deviation of the `DistanceMiles` field in the sample dataset `opensearch_dashboards_sample_data_flights`: + + +```json +GET opensearch_dashboards_sample_data_flights/_search +{ + "size": 0, + "aggs": { + "median_absolute_deviation_DistanceMiles": { + "median_absolute_deviation": { + "field": "DistanceMiles" + } + } + } +} +``` +{% include copy-curl.html %} + +#### Example response + +```json +{ + "took": 35, + "timed_out": false, + "_shards": { + "total": 1, + "successful": 1, + "skipped": 0, + "failed": 0 + }, + "hits": { + "total": { + "value": 10000, + "relation": "gte" + }, + "max_score": null, + "hits": [] + }, + "aggregations": { + "median_absolute_deviation_distanceMiles": { + "value": 1829.8993624441966 + } + } +} +``` + +### Missing + +By default, if a field is missing or has a null value in a document, it is ignored during computation. However, you can specify a value to be used for those missing or null fields by using the `missing` parameter, as shown in the following request: + +```json +GET opensearch_dashboards_sample_data_flights/_search +{ + "size": 0, + "aggs": { + "median_absolute_deviation_distanceMiles": { + "median_absolute_deviation": { + "field": "DistanceMiles", + "missing": 1000 + } + } + } +} +``` +{% include copy-curl.html %} + +#### Example response + +```json +{ + "took": 7, + "timed_out": false, + "_shards": { + "total": 1, + "successful": 1, + "skipped": 0, + "failed": 0 + }, + "hits": { + "total": { + "value": 10000, + "relation": "gte" + }, + "max_score": null, + "hits": [] + }, + "aggregations": { + "median_absolute_deviation_distanceMiles": { + "value": 1829.6443646143355 + } + } +} +``` + +### Compression + +The median absolute deviation is calculated using the [t-digest](https://github.com/tdunning/t-digest/tree/main) data structure, which balances between performance and estimation accuracy through the `compression` parameter (default value: `1000`). Adjusting the `compression` value affects the trade-off between computational efficiency and precision. Lower `compression` values improve performance but may reduce estimation accuracy, while higher values enhance accuracy at the cost of increased computational overhead, as shown in the following request: + +```json +GET opensearch_dashboards_sample_data_flights/_search +{ + "size": 0, + "aggs": { + "median_absolute_deviation_DistanceMiles": { + "median_absolute_deviation": { + "field": "DistanceMiles", + "compression": 10 + } + } + } +} +``` +{% include copy-curl.html %} + +#### Example response + +```json +{ + "took": 1, + "timed_out": false, + "_shards": { + "total": 1, + "successful": 1, + "skipped": 0, + "failed": 0 + }, + "hits": { + "total": { + "value": 10000, + "relation": "gte" + }, + "max_score": null, + "hits": [] + }, + "aggregations": { + "median_absolute_deviation_DistanceMiles": { + "value": 1836.265614211182 + } + } +} +``` diff --git a/_api-reference/analyze-apis.md b/_api-reference/analyze-apis.md index 7c61a6fdcb..10af71c1ad 100644 --- a/_api-reference/analyze-apis.md +++ b/_api-reference/analyze-apis.md @@ -4,6 +4,7 @@ title: Analyze API has_children: true nav_order: 7 redirect_from: + - /api-reference/analyze-apis/perform-text-analysis/ - /opensearch/rest-api/analyze-apis/ - /api-reference/analyze-apis/ --- diff --git a/_api-reference/document-apis/bulk.md b/_api-reference/document-apis/bulk.md index d00230819d..a020fc459d 100644 --- a/_api-reference/document-apis/bulk.md +++ b/_api-reference/document-apis/bulk.md @@ -59,6 +59,7 @@ routing | String | Routes the request to the specified shard. timeout | Time | How long to wait for the request to return. Default `1m`. type | String | (Deprecated) The default document type for documents that don't specify a type. Default is `_doc`. We highly recommend ignoring this parameter and using a type of `_doc` for all indexes. wait_for_active_shards | String | Specifies the number of active shards that must be available before OpenSearch processes the bulk request. Default is 1 (only the primary shard). Set to `all` or a positive integer. Values greater than 1 require replicas. For example, if you specify a value of 3, the index must have two replicas distributed across two additional nodes for the request to succeed. +batch_size | Integer | Specifies the number of documents to be batched and sent to an ingest pipeline to be processed together. Default is `1` (documents are ingested by an ingest pipeline one at a time). If the bulk request doesn't explicitly specify an ingest pipeline or the index doesn't have a default ingest pipeline, then this parameter is ignored. Only documents with `create`, `index`, or `update` actions can be grouped into batches. {% comment %}_source | List | asdf _source_excludes | list | asdf _source_includes | list | asdf{% endcomment %} @@ -123,7 +124,9 @@ All actions support the same metadata: `_index`, `_id`, and `_require_alias`. If { "doc" : { "title": "World War Z" }, "doc_as_upsert": true } ``` - You can specify a script for more complex document updates: + You can specify a script for more complex document updates by defining the script with the `source` or `id` from a document: + + - Script ```json diff --git a/_api-reference/document-apis/reindex.md b/_api-reference/document-apis/reindex.md index 4a0346ede3..2bc3646e68 100644 --- a/_api-reference/document-apis/reindex.md +++ b/_api-reference/document-apis/reindex.md @@ -57,7 +57,7 @@ Your request body must contain the names of the source index and destination ind Field | Description :--- | :--- -conflicts | Indicates to OpenSearch what should happen if the delete by query operation runs into a version conflict. Valid options are `abort` and `proceed`. Default is abort. +conflicts | Indicates to OpenSearch what should happen if the Reindex operation runs into a version conflict. Valid options are `abort` and `proceed`. Default is `abort`. source | Information about the source index to include. Valid fields are `index`, `max_docs`, `query`, `remote`, `size`, `slice`, and `_source`. index | The name of the source index to copy data from. max_docs | The maximum number of documents to reindex. diff --git a/_api-reference/index-apis/flush.md b/_api-reference/index-apis/flush.md new file mode 100644 index 0000000000..fb97e43900 --- /dev/null +++ b/_api-reference/index-apis/flush.md @@ -0,0 +1,78 @@ +--- +layout: default +title: Flush +parent: Index APIs +nav_order: 36 +--- + +# Flush + +**Introduced 1.0** +{: .label .label-purple } + +The Flush API stores all in-memory operations to segments on disk. Operations flushed to an index segment are no longer needed in transaction logs during a cluster restart because these operations are now stored in the Lucene index. + +OpenSearch automatically performs flushes in the background based on conditions like transaction log size, which is controlled by the `index.translog.flush_threshold_size` setting. Use the Flush API sparingly, for example, for manual restarts or to free up memory. + +## Path and HTTP methods + +The Flush API supports the following paths: + +``` +GET /_flush +POST /_flush +GET /{index}/_flush +POST /{index}/_flush +``` + +## Path parameters + +The following table lists the available path parameters. All path parameters are optional. + +| Parameter | Data type | Description | +| :--- | :--- | :--- | +| `` | String | A comma-separated list of indexes, data streams, or index aliases to which the operation is applied. Supports wildcard expressions (`*`). Use `_all` or `*` to specify all indexes and data streams in a cluster. | + +## Query parameters + +The Flush API supports the following query parameters. + +| Parameter | Data type | Description | +| :--- | :--- | :--- | +| `allow_no_indices` | Boolean | When `false`, the request returns an error if any wildcard expression or index alias targets any closed or missing indexes. Default is `true`. | +| `expand_wildcards` | String | Specifies the types of indexes to which wildcard expressions can expand. Supports comma-separated values. Valid values are:
- `all`: Expand to all open and closed indexes, including hidden indexes.
- `open`: Expand to open indexes.
- `closed`: Expand to closed indexes.
- `hidden`: Include hidden indexes when expanding. Must be combined with `open`, `closed`, or both.
- `none`: Do not accept wildcard expressions.
Default is `open`. | +| `force` | Boolean | When `true`, forces a flush to occur even when no changes to the index exist in-memory. Default is `true`. | +| `ignore_unavailable` | Boolean | When `true`, OpenSearch ignores missing or closed indexes. If `false`, OpenSearch returns an error if the force merge operation encounters missing or closed indexes. Default is `false`. | +| `wait_if_ongoing` | Boolean | When `true`, the Flush API does not run while another flush request is active. When `false`, OpenSearch returns an error if another flush request is active. Default is `true`. | + +## Example request: Flush a specific index + +The following example flushes an index named `shakespeare`: + +``` +POST /shakespeare/_flush +``` + +## Example request: Flush all indexes + +The following example flushes all indexes in a cluster: + +``` +POST /_flush +``` + +## Example response + +OpenSearch responds with the number of shards that acknowledged the flush request, the number of shards that completed the request, and the number of shards that failed: + +``` +{ + "_shards": { + "total": 10, + "successful": 10, + "failed": 0 + } +} +``` + + diff --git a/_api-reference/index-apis/get-settings.md b/_api-reference/index-apis/get-settings.md index 37ac291a77..41eb4ea113 100644 --- a/_api-reference/index-apis/get-settings.md +++ b/_api-reference/index-apis/get-settings.md @@ -4,6 +4,7 @@ title: Get settings parent: Index APIs nav_order: 45 redirect_from: + - /opensearch/rest-api/index-apis/get-settings/ - /opensearch/rest-api/index-apis/get-index/ --- diff --git a/_api-reference/index-apis/index.md b/_api-reference/index-apis/index.md index 4c059b3e48..6e1fdbcfa6 100644 --- a/_api-reference/index-apis/index.md +++ b/_api-reference/index-apis/index.md @@ -4,6 +4,7 @@ title: Index APIs has_children: true nav_order: 35 redirect_from: + - /opensearch/rest-api/index-apis/index/ - /opensearch/rest-api/index-apis/ --- diff --git a/_api-reference/index-apis/put-mapping.md b/_api-reference/index-apis/put-mapping.md index 5f6be9f138..47c47fa125 100644 --- a/_api-reference/index-apis/put-mapping.md +++ b/_api-reference/index-apis/put-mapping.md @@ -4,6 +4,7 @@ title: Create or update mappings parent: Index APIs nav_order: 27 redirect_from: + - /opensearch/rest-api/index-apis/put-mapping/ - /opensearch/rest-api/index-apis/update-mapping/ - /opensearch/rest-api/update-mapping/ --- diff --git a/_api-reference/index-apis/refresh.md b/_api-reference/index-apis/refresh.md new file mode 100644 index 0000000000..b72a6c7470 --- /dev/null +++ b/_api-reference/index-apis/refresh.md @@ -0,0 +1,69 @@ +--- +layout: default +title: Refresh index +parent: Index APIs +nav_order: 61 +--- + +# Refresh index +Introduced 1.0 +{: .label .label-purple } + +The Refresh Index API refreshes one or more indexes in an OpenSearch cluster. In the case of data streams, the Refresh Index API refreshes a stream's backing indexes. + +OpenSearch's refresh behavior depends on whether or not `index.refresh_interval` is set: + +- When set, indexes are refreshed based on the `index.refresh_interval` setting (in seconds). For more information about `index.refresh_interval` settings, see [Dynamic index-level index settings]({{site.url}}{{site.baseurl}}/install-and-configure/configuring-opensearch/index-settings/#dynamic-index-level-index-settings). +- When not set, refreshes occur every second until the shard receives no search requests for at least the amount of time specified by the `index.search.idle.after` setting (in seconds). Default is `30s`. + +After a shard becomes idle, the indexes will not refresh until either the next search request or a Refresh Index API request is sent. The first search request on an idle shard will wait for the refresh operation to complete. + +To use the Refresh Index API, you must have write access to the indexes you want to refresh. + +## Path and HTTP methods + +```json +POST /_refresh +GET /_refresh +POST //_refresh +GET //_refresh +``` + +## Path parameters + +The following table lists the available path parameters. All path parameters are optional. + +| Parameter | Data type | Description | +| :--- | :--- | :--- | +| `index` | String | A comma-separated list of index names to be refreshed. Wildcards are accepted.| + +## Query parameters + +The following table lists the available query parameters. All query parameters are optional. + +| Parameter | Data type | Description | +| :--- | :--- | :--- | +| `ignore_unavailable` | Boolean | When `false`, the request returns an error when it targets a missing or closed index. Default is `false`. +| `allow_no_indices` | Boolean | When `false`, the Refresh Index API returns an error when a wildcard expression, index alias, or `_all` targets only closed or missing indexes, even when the request is made against open indexes. Default is `true`. | +| `expand_wildcard` | String | The type of index that the wildcard patterns can match. If the request targets data streams, this argument determines whether the wildcard expressions match any hidden data streams. Supports comma-separated values, such as `open,hidden`. Valid values are `all`, `open`, `closed`, `hidden`, and `none`. + + + +#### Example: Refresh several data streams or indexes + +The following example request refreshes two indexes named `my-index-A` and `my-index-B`: + + +``` +POST /my-index-A,my-index-B/_refresh +``` +{% include copy-curl.html %} + +#### Example: Refresh all data streams and indexes in a cluster + +The following request refreshes all data streams and indexes in a cluster: + +``` +POST /_refresh +``` + diff --git a/_api-reference/msearch-template.md b/_api-reference/msearch-template.md new file mode 100644 index 0000000000..316cc134ff --- /dev/null +++ b/_api-reference/msearch-template.md @@ -0,0 +1,132 @@ +--- +layout: default +title: Multi-search Template +nav_order: 47 +--- + +# Multi-search Template + +**Introduced 1.0** +{: .label .label-purple } + +The Multi-search Template API runs multiple search template requests in a single API request. + +## Path and HTTP methods + +The Multi-search Template API uses the following paths: + +``` +GET /_msearch/template +POST /_msearch/template +GET /{index}/_msearch/template +POST /{index}/_msearch/template +``` + +## Request body + +The multi-search template request body follows this pattern, similar to the [Multi-search API]({{site.url}}{{site.baseurl}}/api-reference/multi-search/) pattern: + +``` +Metadata\n +Query\n +Metadata\n +Query\n + +``` + +- Metadata lines include options, such as which indexes to search and the type of search. +- Query lines use [query DSL]({{site.url}}{{site.baseurl}}/opensearch/query-dsl/). + +Like the [bulk]({{site.url}}{{site.baseurl}}/api-reference/document-apis/bulk/) operation, the JSON doesn't need to be minified---spaces are fine---but it does need to be on a single line. OpenSearch uses newline characters to parse multi-search requests and requires that the request body end with a newline character. + +## URL parameters and metadata options + +All multi-search template URL parameters are optional. Some can also be applied per search as part of each metadata line. + +Parameter | Type | Description | Supported in metadata +:--- | :--- | :--- | :--- +allow_no_indices | Boolean | Specifies whether to ignore wildcards that don't match any indexes. Default is `true`. | Yes +cancel_after_time_interval | Time | The interval of time after which the search request will be canceled. Supported at both parent and child request levels. The order of precedence is child-level parameter, parent-level parameter, and [cluster setting]({{site.url}}{{site.baseurl}}/api-reference/cluster-settings/). Default is `-1`. | Yes +css_minimize_roundtrips | Boolean | Specifies whether OpenSearch should try to minimize the number of network round trips between the coordinating node and remote clusters (only applicable to cross-cluster search requests). Default is `true`. | No +expand_wildcards | Enum | Expands wildcard expressions to concrete indexes. Combine multiple values with commas. Supported values are `all`, `open`, `closed`, `hidden`, and `none`. Default is `open`. | Yes +ignore_unavailable | Boolean | If an index or shard from the index list doesn’t exist, then this setting specifies whether to ignore the missing index or shard rather than fail the query. Default is `false`. | Yes +max_concurrent_searches | Integer | The maximum number of concurrent searches. The default depends on your node count and search thread pool size. Higher values can improve performance, but there may be a risk of overloading the cluster. | No +max_concurrent_shard_requests | Integer | The maximum number of concurrent shard requests that each search executes per node. Default is `5`. Higher values can improve performance, but there may be a risk of overloading the cluster. | No +pre_filter_shard_size | Integer | Default is `128`. | No +rest_total_hits_as_int | String | Specifies whether the `hits.total` property is returned as an integer (`true`) or an object (`false`). Default is `false`. | No +search_type | String | Affects the relevance score. Valid options are `query_then_fetch` and `dfs_query_then_fetch`. `query_then_fetch` scores documents using term and document frequencies for a single shard (faster, less accurate), whereas `dfs_query_then_fetch` uses term and document frequencies across all shards (slower, more accurate). Default is `query_then_fetch`. | Yes +typed_keys | Boolean | Specifies whether to prefix aggregation names with their internal types in the response. Default is `false`. | No + +## Metadata-only options + +Some options can't be applied as URL parameters to the entire request. Instead, you can apply them per search as part of each metadata line. All are optional. + +Option | Type | Description +:--- | :--- | :--- +index | String, string array | If you don't specify an index or multiple indexes as part of the URL (or want to override the URL value for an individual search), you can include it under this option. Examples include `"logs-*"` and `["my-store", "sample_data_ecommerce"]`. +preference | String | Specifies the nodes or shards on which you want to perform the search. This setting can be useful for testing, but in most situations, the default behavior provides the best search latencies. Options include `_local`, `_only_local`, `_prefer_nodes`, `_only_nodes`, and `_shards`. These last three options accept a list of nodes or shards. Examples include `"_only_nodes:data-node1,data-node2"` and `"_shards:0,1`. +request_cache | Boolean | Specifies whether to cache results, which can improve latency for repeated searches. Default is to use the `index.requests.cache.enable` setting for the index (which defaults to `true` for new indexes). +routing | String | Comma-separated custom routing values, for example, `"routing": "value1,value2,value3"`. + +## Example + +The following example `msearch/template` API request runs queries against a single index using multiple templates named `line_search_template` and `play_search_template`: + +### Request + +```json +GET _msearch/template +{"index":"shakespeare"} +{"id":"line_search_template","params":{"text_entry":"All the world's a stage","limit":false,"size":2}} +{"index":"shakespeare"} +{"id":"play_search_template","params":{"play_name":"Henry IV"}} +``` +{% include copy-curl.html %} + +### Response + +OpenSearch returns an array with the results of each search in the same order as in the multi-search template request: + +```json +{ + "took": 5, + "responses": [ + { + "took": 5, + "timed_out": false, + "_shards": { + "total": 1, + "successful": 1, + "skipped": 0, + "failed": 0 + }, + "hits": { + "total": { + "value": 0, + "relation": "eq" + }, + "max_score": null, + "hits": [] + } + }, + { + "took": 3, + "timed_out": false, + "_shards": { + "total": 1, + "successful": 1, + "skipped": 0, + "failed": 0 + }, + "hits": { + "total": { + "value": 0, + "relation": "eq" + }, + "max_score": null, + "hits": [] + } + } + ] +} +``` diff --git a/_api-reference/multi-search.md b/_api-reference/multi-search.md index 19e6fc34fc..ff04b2d075 100644 --- a/_api-reference/multi-search.md +++ b/_api-reference/multi-search.md @@ -6,12 +6,13 @@ redirect_from: - /opensearch/rest-api/multi-search/ --- -# Multi-search +# Multi-search **Introduced 1.0** {: .label .label-purple } As the name suggests, the multi-search operation lets you bundle multiple search requests into a single request. OpenSearch then executes the searches in parallel, so you get back the response more quickly compared to sending one request per search. OpenSearch executes each search independently, so the failure of one doesn't affect the others. + ## Example ```json @@ -27,6 +28,8 @@ GET _msearch ## Path and HTTP methods +The Multi-search API uses the following paths: + ``` GET _msearch GET /_msearch @@ -34,7 +37,6 @@ POST _msearch POST /_msearch ``` - ## Request body The multi-search request body follows this pattern: diff --git a/_api-reference/nodes-apis/nodes-stats.md b/_api-reference/nodes-apis/nodes-stats.md index 87365fa900..145b3d5b24 100644 --- a/_api-reference/nodes-apis/nodes-stats.md +++ b/_api-reference/nodes-apis/nodes-stats.md @@ -40,6 +40,7 @@ indices | Index statistics, such as size, document count, and search, index, and os | Statistics about the host OS, including load, memory, and swapping. process | Statistics about processes, including their memory consumption, open file descriptors, and CPU usage. jvm | Statistics about the JVM, including memory pool, buffer pool, and garbage collection, and the number of loaded classes. +thread_pool | Statistics about each thread pool for the node. fs | File system statistics, such as read/write statistics, data path, and free disk space. transport | Transport layer statistics about send/receive in cluster communication. http | Statistics about the HTTP layer. @@ -51,8 +52,12 @@ adaptive_selection | Statistics about adaptive replica selection, which selects script_cache | Statistics about script cache. indexing_pressure | Statistics about the node's indexing pressure. shard_indexing_pressure | Statistics about shard indexing pressure. +search_backpressure | Statistics related to search backpressure. +cluster_manager_throttling | Statistics related to throttled tasks on the cluster manager node. +weighted_routing | Statistics relevant to weighted round robin requests. resource_usage_stats | Node-level resource usage statistics, such as CPU and JVM memory. admission_control | Statistics about admission control. +caches | Statistics about caches. To filter the information returned for the `indices` metric, you can use specific `index_metric` values. You can use these only when you use the following query types: @@ -87,6 +92,18 @@ GET _nodes/stats/indices/docs,search ``` {% include copy-curl.html %} +You can also use specific `index_metric` values in the `caches` metric to specify which caches will return statistics. +The following index metrics are supported: + +- request_cache + +For example, the following query requests statistics for the `request_cache`: + +```json +GET _nodes/stats/caches/request_cache +``` +{% include copy-curl.html %} + ## Query parameters The following table lists the available query parameters. All query parameters are optional. @@ -97,7 +114,7 @@ completion_fields | String | The fields to include in completion statistics. Sup fielddata_fields | String | The fields to include in fielddata statistics. Supports comma-separated lists and wildcard expressions. fields | String | The fields to include. Supports comma-separated lists and wildcard expressions. groups | String | A comma-separated list of search groups to include in the search statistics. -level | String | Specifies whether statistics are aggregated at the cluster, index, or shard level. Valid values are `indices`, `node`, and `shard`. +level | String | Specifies whether statistics for the `indices` metric are aggregated at the cluster, index, or shard level. Valid values are `indices`, `node`, and `shard`. When used for the `caches` metric, `indices`, `shard`, and `tier` are valid. The `tier` value is ignored if the [tiered spillover cache]({{site.url}}{{site.baseurl}}/search-plugins/caching/tiered-cache/) is not in use. timeout | Time | Sets the time limit for node response. Default is `30s`. include_segment_file_sizes | Boolean | If segment statistics are requested, this field specifies to return the aggregated disk usage of every Lucene index file. Default is `false`. @@ -754,6 +771,16 @@ Select the arrow to view the example response. } } } + }, + "caches" : { + "request_cache" : { + "size_in_bytes" : 1649, + "evictions" : 0, + "hit_count" : 0, + "miss_count" : 18, + "item_count" : 18, + "store_name" : "opensearch_onheap" + } } } } @@ -807,8 +834,11 @@ http.total_opened | Integer | The total number of HTTP connections the node has [indexing_pressure](#indexing_pressure) | Object | Statistics related to the node's indexing pressure. [shard_indexing_pressure](#shard_indexing_pressure) | Object | Statistics related to indexing pressure at the shard level. [search_backpressure]({{site.url}}{{site.baseurl}}/opensearch/search-backpressure#search-backpressure-stats-api) | Object | Statistics related to search backpressure. +[cluster_manager_throttling](#cluster_manager_throttling) | Object | Statistics related to throttled tasks on the cluster manager node. +[weighted_routing](#weighted_routing) | Object | Statistics relevant to weighted round robin requests. [resource_usage_stats](#resource_usage_stats) | Object | Statistics related to resource usage for the node. [admission_control](#admission_control) | Object | Statistics related to admission control for the node. +[caches](#caches) | Object | Statistics related to caches on the node. ### `indices` @@ -997,20 +1027,20 @@ cpu.load_average | Object | Statistics about load averages for the system. cpu.load_average.1m | Float | The load average for the system for the time period of one minute. cpu.load_average.5m | Float | The load average for the system for the time period of five minutes. cpu.load_average.15m | Float | The load average for the system for the time period of 15 minutes. -cpu.mem | Object | Statistics about memory usage for the node. -cpu.mem.total_in_bytes | Integer | The total amount of physical memory, in bytes. -cpu.mem.free_in_bytes | Integer | The total amount of free physical memory, in bytes. -cpu.mem.used_in_bytes | Integer | The total amount of used physical memory, in bytes. -cpu.mem.free_percent | Integer | The percentage of memory that is free. -cpu.mem.used_percent | Integer | The percentage of memory that is used. -cpu.swap | Object | Statistics about swap space for the node. -cpu.swap.total_in_bytes | Integer | The total amount of swap space, in bytes. -cpu.swap.free_in_bytes | Integer | The total amount of free swap space, in bytes. -cpu.swap.used_in_bytes | Integer | The total amount of used swap space, in bytes. -cpu.cgroup | Object | Contains cgroup statistics for the node. Returned for Linux only. -cpu.cgroup.cpuacct | Object | Statistics about the cpuacct control group for the node. -cpu.cgroup.cpu | Object | Statistics about the CPU control group for the node. -cpu.cgroup.memory | Object | Statistics about the memory control group for the node. +mem | Object | Statistics about memory usage for the node. +mem.total_in_bytes | Integer | The total amount of physical memory, in bytes. +mem.free_in_bytes | Integer | The total amount of free physical memory, in bytes. +mem.used_in_bytes | Integer | The total amount of used physical memory, in bytes. +mem.free_percent | Integer | The percentage of memory that is free. +mem.used_percent | Integer | The percentage of memory that is used. +swap | Object | Statistics about swap space for the node. +swap.total_in_bytes | Integer | The total amount of swap space, in bytes. +swap.free_in_bytes | Integer | The total amount of free swap space, in bytes. +swap.used_in_bytes | Integer | The total amount of used swap space, in bytes. +cgroup | Object | Contains cgroup statistics for the node. Returned for Linux only. +cgroup.cpuacct | Object | Statistics about the cpuacct control group for the node. +cgroup.cpu | Object | Statistics about the CPU control group for the node. +cgroup.memory | Object | Statistics about the memory control group for the node. ### `process` @@ -1082,7 +1112,7 @@ active | Integer | The number of active threads in the pool. rejected | Integer | The number of tasks that have been rejected. largest | Integer | The peak number of threads in the pool. completed | Integer | The number of tasks completed. -total_wait_time | Integer | The total amount of time tasks spent waiting in the thread pool queue. Currently, only `search`, `search_throttled`, and `index_searcher` thread pools support this metric. +total_wait_time_in_nanos | Integer | The total amount of time that tasks spend waiting in the thread pool queue. Currently, only `search`, `search_throttled`, and `index_searcher` thread pools support this metric. ### `fs` @@ -1256,6 +1286,25 @@ total_rejections_breakup_shadow_mode.throughput_degradation_limits | Integer | T enabled | Boolean | Specifies whether the shard indexing pressure feature is turned on for the node. enforced | Boolean | If true, the shard indexing pressure runs in enforced mode (there are rejections). If false, the shard indexing pressure runs in shadow mode (there are no rejections, but statistics are recorded and can be retrieved in the `total_rejections_breakup_shadow_mode` object). Only applicable if shard indexing pressure is enabled. +### `cluster_manager_throttling` + +The `cluster_manager_throttling` object contains statistics about throttled tasks on the cluster manager node. It is populated only for the node that is currently elected as the cluster manager. + +Field | Field type | Description +:--- | :--- | :--- +stats | Object | Statistics about throttled tasks on the cluster manager node. +stats.total_throttled_tasks | Long | The total number of throttled tasks. +stats.throttled_tasks_per_task_type | Object | A breakdown of statistics by individual task type, specified as key-value pairs. The keys are individual task types, and their values represent the number of requests that were throttled. + +### `weighted_routing` + +The `weighted_routing` object contains statistics about weighted round robin requests. Specifically, it contains a counter of times this node has server a request while it was "zoned out". + +Field | Field type | Description +:--- |:-----------| :--- +stats | Object | Statistics about weighted routing. +fail_open_count | Integer | Number of times a shard on this node has served a request while the routing weight for the node was set to zero. + ### `resource_usage_stats` The `resource_usage_stats` object contains the resource usage statistics. Each entry is specified by the node ID and has the following properties. @@ -1278,6 +1327,33 @@ admission_control.global_cpu_usage.transport.rejection_count.indexing | Integer admission_control.global_io_usage.transport.rejection_count.search | Integer | The total number of search rejections in the transport layer when the node IO usage limit was met. Any additional search requests are rejected until the system recovers. The CPU usage limit is configured in the `admission_control.search.io_usage.limit` setting (Linux only). admission_control.global_io_usage.transport.rejection_count.indexing | Integer | The total number of indexing rejections in the transport layer when the node IO usage limit was met. Any additional indexing requests are rejected until the system recovers. The IO usage limit is configured in the `admission_control.indexing.io_usage.limit` setting (Linux only). +### `caches` + +Because this API supports the experimental [tiered caching feature]({{site.url}}{{site.baseurl}}/search-plugins/caching/tiered-cache/), the responses found in this section may change. If the tiered caching feature flag is not enabled, the API will return `0` for all values. +{: .warning} + +The `caches` object contains cache statistics, such as the `request_cache` statistics. The total values within each sub-metric are always returned, regardless of the value of the query parameter `level`. + +Field | Field type | Description +:--- | :--- | :--- +request_cache | Object | Statistics for the request cache. +request_cache.size_in_bytes | Integer | The total size, in bytes, of the request cache. +request_cache.evictions | Integer | The total number of evictions from the request cache. +request_cache.hit_count | Integer | The total hit count for the request cache. +request_cache.miss_count | Integer | The total miss count for the request cache. +request_cache.item_count | Integer | The total number of items in the request cache. +request_cache.store_name | String | The name of the store type used by the request cache. See [tiered cache]({{site.url}}{{site.baseurl}}/search-plugins/caching/tiered-cache/) for more information. + +If the `level` query parameter is set to one of its valid values, `indices`, `shard`, or `tier`, additional fields will be present in `caches.request_cache` that categorize the values by these levels. +For example, if `level=indices,tier`, the tiered cache is in use, and the node has indexes named `index0` and `index1`, then the `caches` object will contain the same five metrics for each combination of level values, as shown in the following table. + +Field | Field type | Description +:--- | :--- | :--- +request_cache.indices.index0.tier.on_heap | Object | Contains the five metrics for `index0` on the heap tier. +request_cache.indices.index0.tier.disk | Object | Contains the five metrics for `index0` on the disk tier. +request_cache.indices.index1.tier.on_heap | Object | Contains the five metrics for `index1` on the heap tier. +request_cache.indices.index1.tier.disk | Object | Contains the five metrics for `index1` on the disk tier. + ## Required permissions If you use the Security plugin, make sure you have the appropriate permissions: `cluster:monitor/nodes/stats`. diff --git a/_api-reference/security-apis.md b/_api-reference/security-apis.md new file mode 100644 index 0000000000..db3334fb0e --- /dev/null +++ b/_api-reference/security-apis.md @@ -0,0 +1,20 @@ +--- +layout: default +title: Security APIs +nav_order: 84 +--- + +# Security APIs + +Security APIs provide information that can be very useful in troubleshooting connection and configuration issues. + +API | Method | Description +:--- | :--- | :--- +`/_plugins/_security/whoami` | GET/POST | Returns basic details about the logged-in user. +`/_opendistro/_security/sslinfo` | GET | Returns details about the SSL connection when using certificate authentication. +`/_plugins/_security/api/permissionsinfo` | GET | Returns permission details for the logged-in user. +`/_plugins/_security/authinfo` | GET/POST | Returns the backend roles and OpenSearch roles mapped to the logged-in user. +`/_plugins/_security/api/ssl/certs` | GET | Displays the details and expiration dates of the certificates used on the OpenSearch HTTP and transport communication layers. Can only be called by users with the `superadmin` certificate. +`/_plugins/_security/api/ssl/transport/reloadcerts` | PUT | Reloads the certificates on the `transport` layer. For more information, see [Reload TLS certificates on the transport layer]({{site.url}}{{site.baseurl}}/security/configuration/tls/#reload-tls-certificates-on-the-transport-layer). +`/_plugins/_security/api/ssl/http/reloadcerts` | PUT | Reloads the certificates on the `http` layer. For more information, see [Reload TLS certificates on the http layer]({{site.url}}{{site.baseurl}}/security/configuration/tls/#reload-tls-certificates-on-the-http-layer). + diff --git a/_automating-configurations/api/delete-workflow.md b/_automating-configurations/api/delete-workflow.md index db3a340cee..13cd5ae5dc 100644 --- a/_automating-configurations/api/delete-workflow.md +++ b/_automating-configurations/api/delete-workflow.md @@ -7,9 +7,11 @@ nav_order: 80 # Delete a workflow -When you no longer need a workflow template, you can delete it by calling the Delete Workflow API. +When you no longer need a workflow template, you can delete it by calling the Delete Workflow API. -Note that deleting a workflow only deletes the stored template but does not deprovision its resources. +Note that deleting a workflow only deletes the stored template---it does not deprovision its resources. + +When a workflow is deleted, its corresponding status (returned by the [Workflow State API]({{site.url}}{{site.baseurl}}/automating-configurations/api/get-workflow-status/)) is also deleted unless either the provisioning status is `IN_PROGRESS` or resources have been provisioned. ## Path and HTTP methods @@ -25,13 +27,26 @@ The following table lists the available path parameters. | :--- | :--- | :--- | | `workflow_id` | String | The ID of the workflow to be retrieved. Required. | +## Query parameters + +The following table lists the available query parameters. All query parameters are optional. + +| Parameter | Data type | Description | +| :--- | :--- | :--- | +| `clear_status` | Boolean | Determines whether to delete the workflow state (without deprovisioning resources) after deleting the template. OpenSearch deletes the workflow state only if the provisioning status is not `IN_PROGRESS`. Default is `false`. | + #### Example request -``` +```json DELETE /_plugins/_flow_framework/workflow/8xL8bowB8y25Tqfenm50 ``` {% include copy-curl.html %} +```json +DELETE /_plugins/_flow_framework/workflow/8xL8bowB8y25Tqfenm50?clear_status=true +``` +{% include copy-curl.html %} + #### Example response If the workflow exists, a delete response contains the status of the deletion, where the `result` field is set to `deleted` on success or `not_found` if the workflow does not exist (it may have already been deleted): @@ -50,4 +65,4 @@ If the workflow exists, a delete response contains the status of the deletion, w "_seq_no": 2, "_primary_term": 1 } -``` \ No newline at end of file +``` diff --git a/_automating-configurations/workflow-steps.md b/_automating-configurations/workflow-steps.md index 2fba435ec7..43685a957a 100644 --- a/_automating-configurations/workflow-steps.md +++ b/_automating-configurations/workflow-steps.md @@ -42,6 +42,25 @@ The following table lists the workflow step types. The `user_inputs` fields for |`create_index`|[Create Index]({{site.url}}{{site.baseurl}}/api-reference/index-apis/create-index/) | Creates a new OpenSearch index. The inputs include `index_name`, which should be the name of the index to be created, and `configurations`, which contains the payload body of a regular REST request for creating an index. |`create_ingest_pipeline`|[Create Ingest Pipeline]({{site.url}}{{site.baseurl}}/ingest-pipelines/create-ingest/) | Creates or updates an ingest pipeline. The inputs include `pipeline_id`, which should be the ID of the pipeline, and `configurations`, which contains the payload body of a regular REST request for creating an ingest pipeline. |`create_search_pipeline`|[Create Search Pipeline]({{site.url}}{{site.baseurl}}/search-plugins/search-pipelines/creating-search-pipeline/) | Creates or updates a search pipeline. The inputs include `pipeline_id`, which should be the ID of the pipeline, and `configurations`, which contains the payload body of a regular REST request for creating a search pipeline. +|`reindex`|[Reindex]({{site.url}}{{site.baseurl}}/api-reference/document-apis/reindex/) | The reindex document API operation lets you copy all or a subset of your data from a source index into a destination index. The input includes source_index, destination_index, and the following optional parameters from the document reindex API: `refresh`, `requests_per_second`, `require_alias`, `slices`, and `max_docs`. For more information, see [Reindexing considerations](#reindexing-considerations). + +## Reindexing considerations + +Reindexing can be a resource-intensive operation, and if not managed properly, it can potentially destabilize your cluster. + +When using a `reindex` step, follow these best practices to ensure a smooth reindexing process and prevent cluster instability: + +- **Cluster scaling**: Before initiating a reindexing operation, ensure that your OpenSearch cluster is properly scaled to handle the additional workload. Increase the number of nodes and adjust resource allocation (CPU, memory, and disk) as needed to accommodate the reindexing process without impacting other operations. + +- **Request rate control**: Use the `requests_per_second` parameter to control the rate at which the reindexing requests are sent to the cluster. This helps to regulate the load on the cluster and prevent resource exhaustion. Start with a lower value and gradually increase it based on your cluster's capacity and performance. + +- **Slicing and parallelization**: The `slices` parameter allows you to divide the reindexing process into smaller, parallel tasks. This can help distribute the workload across multiple nodes and improve overall performance. However, be cautious when increasing the number of slices because adding slices can increase resource consumption. + +- **Monitoring and adjustments**: Closely monitor your cluster performance metrics (such as CPU, memory, disk usage, and thread pools) during the reindexing process. If you notice any signs of resource contention or performance degradation, adjust the reindexing parameters accordingly or consider pausing the operation until the cluster stabilizes. + +- **Prioritization and scheduling**: If possible, schedule reindexing operations during off-peak hours or periods of lower cluster utilization to minimize the impact on other operations and user traffic. + +By following these best practices and carefully managing the reindexing process, you can ensure that your OpenSearch cluster remains stable and performant while efficiently copying data between indexes. ## Additional fields diff --git a/_automating-configurations/workflow-templates.md b/_automating-configurations/workflow-templates.md index 1133148c8f..62406ae069 100644 --- a/_automating-configurations/workflow-templates.md +++ b/_automating-configurations/workflow-templates.md @@ -138,5 +138,8 @@ The following table lists the supported workflow templates. To use a workflow te | `multimodal_search_with_bedrock_titan` | Deploys an Amazon Bedrock multimodal model and configures an ingest pipeline with a `text_image_embedding` processor and a k-NN index for [multimodal search]({{site.url}}{{site.baseurl}}/search-plugins/multimodal-search/). You must provide your AWS credentials. | `create_connector.credential.access_key`, `create_connector.credential.secret_key`, `create_connector.credential.session_token` |[Defaults](https://github.com/opensearch-project/flow-framework/blob/2.13/src/main/resources/defaults/multimodal-search-bedrock-titan-defaults.json) | | `hybrid_search` | Configures [hybrid search]({{site.url}}{{site.baseurl}}/search-plugins/hybrid-search/):
- Creates an ingest pipeline, a k-NN index, and a search pipeline with a `normalization_processor`. You must provide the model ID of the text embedding model to be used. | `create_ingest_pipeline.model_id` |[Defaults](https://github.com/opensearch-project/flow-framework/blob/2.13/src/main/resources/defaults/hybrid-search-defaults.json) | | `conversational_search_with_llm_deploy` | Deploys a large language model (LLM) (by default, Cohere Chat) and configures a search pipeline with a `retrieval_augmented_generation` processor for [conversational search]({{site.url}}{{site.baseurl}}/search-plugins/conversational-search/). | `create_connector.credential.key` |[Defaults](https://github.com/opensearch-project/flow-framework/blob/2.13/src/main/resources/defaults/conversational-search-defaults.json) | +| `semantic_search_with_reindex` | Configures [semantic search]({{site.url}}{{site.baseurl}}/search-plugins/semantic-search/) with a newly deployed Cohere embedding model. The model is configured to reindex a source index into a newly configured k-NN index. You must provide the API key for the Cohere model along with the source index to be reindexed. | `create_connector.credential.key`, `reindex.source_index`|[Defaults](https://github.com/opensearch-project/flow-framework/blob/main/src/main/resources/defaults/semantic-search-with-reindex-defaults.json) | +| `semantic_search_with_local_model` | Configures [semantic search]({{site.url}}{{site.baseurl}}/search-plugins/semantic-search/) and deploys a pretrained model (`msmarco-distilbert-base-tas-b`). Adds a [`query_enricher`]({{site.url}}{{site.baseurl}}/search-plugins/search-pipelines/neural-query-enricher/) search processor that sets a default model ID for neural queries and creates a linked k-NN index called `my-nlp-index`. You must provide the API key for the Cohere model. | None | [Defaults](https://github.com/opensearch-project/flow-framework/blob/main/src/main/resources/defaults/semantic-search-with-local-model-defaults.json) | +| `hybrid_search_with_local_model` | Configures [hybrid search]({{site.url}}{{site.baseurl}}/search-plugins/hybrid-search/) and deploys a pretrained model (`msmarco-distilbert-base-tas-b`). Creates an ingest pipeline, a k-NN index, and a search pipeline with a `normalization_processor`. | None | [Defaults](https://github.com/opensearch-project/flow-framework/blob/main/src/main/resources/defaults/hybrid-search-with-local-model-defaults.json) | diff --git a/_benchmark/index.md b/_benchmark/index.md index 25b3738e7d..1a71d57de9 100644 --- a/_benchmark/index.md +++ b/_benchmark/index.md @@ -22,7 +22,7 @@ OpenSearch Benchmark can be installed directly on a compatible host running Linu The following diagram visualizes how OpenSearch Benchmark works when run against a local host: -![Benchmark workflow]({{site.url}}{{site.baseurl}}/images/benchmark/OSB-workflow.png). +![Benchmark workflow]({{site.url}}{{site.baseurl}}/images/benchmark/osb-workflow.jpg). The OpenSearch Benchmark documentation is split into five sections: diff --git a/_benchmark/quickstart.md b/_benchmark/quickstart.md index 0c23f74953..a6bcd59819 100644 --- a/_benchmark/quickstart.md +++ b/_benchmark/quickstart.md @@ -18,7 +18,7 @@ To perform the Quickstart steps, you'll need to fulfill the following prerequisi ## Set up an OpenSearch cluster -If you don't already have an active OpenSearch cluster, you can launch a new OpenSearch cluster to use with OpenSerch Benchmark. +If you don't already have an active OpenSearch cluster, you can launch a new OpenSearch cluster to use with OpenSearch Benchmark. - Using **Docker Compose**. For instructions on how to use Docker Compose, see [OpenSearch Quickstart]({{site.url}}{{site.baseurl}}/quickstart/). - Using **Tar**. For instructions on how to install OpenSearch with Tar, see [Installing OpenSearch > Tarball]({{site.url}}{{site.baseurl}}/install-and-configure/install-opensearch/tar#step-1-download-and-unpack-opensearch). diff --git a/_benchmark/reference/commands/command-flags.md b/_benchmark/reference/commands/command-flags.md index ca0606f07f..6520f80803 100644 --- a/_benchmark/reference/commands/command-flags.md +++ b/_benchmark/reference/commands/command-flags.md @@ -3,7 +3,8 @@ layout: default title: Command flags nav_order: 51 parent: Command reference -redirect_from: /benchmark/commands/command-flags/ +redirect_from: + - /benchmark/commands/command-flags/ grand_parent: OpenSearch Benchmark Reference --- diff --git a/_benchmark/reference/commands/compare.md b/_benchmark/reference/commands/compare.md index dc7ed2f558..a9eb8bcc10 100644 --- a/_benchmark/reference/commands/compare.md +++ b/_benchmark/reference/commands/compare.md @@ -4,7 +4,8 @@ title: compare nav_order: 55 parent: Command reference grand_parent: OpenSearch Benchmark Reference -redirect_from: /benchmark/commands/compare/ +redirect_from: + - /benchmark/commands/compare/ --- diff --git a/_benchmark/reference/commands/download.md b/_benchmark/reference/commands/download.md index 580e7ef84d..bc29dfd5f7 100644 --- a/_benchmark/reference/commands/download.md +++ b/_benchmark/reference/commands/download.md @@ -4,7 +4,8 @@ title: download nav_order: 60 parent: Command reference grand_parent: OpenSearch Benchmark Reference -redirect_from: /benchmark/commands/download/ +redirect_from: + - /benchmark/commands/download/ --- diff --git a/_benchmark/reference/commands/execute-test.md b/_benchmark/reference/commands/execute-test.md index d8a3e14dbd..82b677d900 100644 --- a/_benchmark/reference/commands/execute-test.md +++ b/_benchmark/reference/commands/execute-test.md @@ -4,7 +4,8 @@ title: execute-test nav_order: 65 parent: Command reference grand_parent: OpenSearch Benchmark Reference -redirect_from: /benchmark/commands/execute-test/ +redirect_from: + - /benchmark/commands/execute-test/ --- diff --git a/_benchmark/reference/commands/info.md b/_benchmark/reference/commands/info.md index c8c20ad110..3bfefabe99 100644 --- a/_benchmark/reference/commands/info.md +++ b/_benchmark/reference/commands/info.md @@ -4,7 +4,8 @@ title: info nav_order: 75 parent: Command reference grand_parent: OpenSearch Benchmark Reference -redirect_from: /benchmark/commands/info/ +redirect_from: + - /benchmark/commands/info/ --- diff --git a/_benchmark/reference/commands/list.md b/_benchmark/reference/commands/list.md index ed10f02a3b..1c51cfa27e 100644 --- a/_benchmark/reference/commands/list.md +++ b/_benchmark/reference/commands/list.md @@ -4,7 +4,8 @@ title: list nav_order: 80 parent: Command reference grand_parent: OpenSearch Benchmark Reference -redirect_from: /benchmark/commands/list/ +redirect_from: + - /benchmark/commands/list/ --- diff --git a/_benchmark/reference/index.md b/_benchmark/reference/index.md index bc7a423b49..4c71443259 100644 --- a/_benchmark/reference/index.md +++ b/_benchmark/reference/index.md @@ -3,6 +3,8 @@ layout: default title: OpenSearch Benchmark Reference nav_order: 25 has_children: true +redirect_from: + - /benchmark/commands/index/ --- # OpenSearch Benchmark Reference diff --git a/_benchmark/reference/metrics/metric-keys.md b/_benchmark/reference/metrics/metric-keys.md index aa45c9d93a..63ad9b6140 100644 --- a/_benchmark/reference/metrics/metric-keys.md +++ b/_benchmark/reference/metrics/metric-keys.md @@ -4,7 +4,8 @@ title: Metric keys nav_order: 35 parent: Metrics reference grand_parent: OpenSearch Benchmark Reference -redirect_from: /benchmark/metrics/metric-keys/ +redirect_from: + - /benchmark/metrics/metric-keys/ --- # Metric keys diff --git a/_benchmark/reference/metrics/metric-records.md b/_benchmark/reference/metrics/metric-records.md index 659f8b82fe..1809401783 100644 --- a/_benchmark/reference/metrics/metric-records.md +++ b/_benchmark/reference/metrics/metric-records.md @@ -4,7 +4,8 @@ title: Metric records nav_order: 30 parent: Metrics reference grand_parent: OpenSearch Benchmark Reference -redirect_from: /benchmark/metrics/metric-records/ +redirect_from: + - /benchmark/metrics/metric-records/ --- # Metric records diff --git a/_benchmark/reference/workloads/corpora.md b/_benchmark/reference/workloads/corpora.md index daa2ae6570..0e8d408e9a 100644 --- a/_benchmark/reference/workloads/corpora.md +++ b/_benchmark/reference/workloads/corpora.md @@ -4,7 +4,8 @@ title: corpora parent: Workload reference grand_parent: OpenSearch Benchmark Reference nav_order: 70 -redirect_from: /benchmark/workloads/corpora/ +redirect_from: + - /benchmark/workloads/corpora/ --- diff --git a/_benchmark/reference/workloads/index.md b/_benchmark/reference/workloads/index.md index 1dd609cacb..fa7346cad9 100644 --- a/_benchmark/reference/workloads/index.md +++ b/_benchmark/reference/workloads/index.md @@ -16,7 +16,7 @@ A workload is a specification of one or more benchmarking scenarios. A workload This section provides a list of options and examples you can use when customizing or using a workload. -For more information about what comprises a workload, see [Anatomy of a workload](({{site.url}}{{site.baseurl}}/benchmark/understanding-workloads/anatomy-of-a-workload/). +For more information about what comprises a workload, see [Anatomy of a workload]({{site.url}}{{site.baseurl}}/benchmark/user-guide/understanding-workloads/anatomy-of-a-workload/). ## Workload examples diff --git a/_benchmark/reference/workloads/indices.md b/_benchmark/reference/workloads/indices.md index daaf6101f3..1478179bae 100644 --- a/_benchmark/reference/workloads/indices.md +++ b/_benchmark/reference/workloads/indices.md @@ -4,7 +4,8 @@ title: indices parent: Workload reference grand_parent: OpenSearch Benchmark Reference nav_order: 65 -redirect_from: /benchmark/workloads/indices/ +redirect_from: + - /benchmark/workloads/indices/ --- diff --git a/_benchmark/user-guide/configuring-benchmark.md b/_benchmark/user-guide/configuring-benchmark.md index 4cbf223b39..2be467d587 100644 --- a/_benchmark/user-guide/configuring-benchmark.md +++ b/_benchmark/user-guide/configuring-benchmark.md @@ -3,7 +3,8 @@ layout: default title: Configuring OpenSearch Benchmark nav_order: 7 parent: User guide -redirect_from: /benchmark/configuring-benchmark/ +redirect_from: + - /benchmark/configuring-benchmark/ --- # Configuring OpenSearch Benchmark diff --git a/_benchmark/user-guide/creating-custom-workloads.md b/_benchmark/user-guide/creating-custom-workloads.md index d06610467f..ee0dca1ce9 100644 --- a/_benchmark/user-guide/creating-custom-workloads.md +++ b/_benchmark/user-guide/creating-custom-workloads.md @@ -4,6 +4,7 @@ title: Creating custom workloads nav_order: 10 parent: User guide redirect_from: + - /benchmark/user-guide/creating-custom-workloads/ - /benchmark/creating-custom-workloads/ - /benchmark/user-guide/creating-osb-workloads/ --- diff --git a/_benchmark/user-guide/installing-benchmark.md b/_benchmark/user-guide/installing-benchmark.md index d3387deefb..8383cfb2f9 100644 --- a/_benchmark/user-guide/installing-benchmark.md +++ b/_benchmark/user-guide/installing-benchmark.md @@ -3,7 +3,8 @@ layout: default title: Installing OpenSearch Benchmark nav_order: 5 parent: User guide -redirect_from: /benchmark/installing-benchmark/ +redirect_from: + - /benchmark/installing-benchmark/ --- # Installing OpenSearch Benchmark diff --git a/_config.yml b/_config.yml index e5cce4e34f..be015cec06 100644 --- a/_config.yml +++ b/_config.yml @@ -5,9 +5,9 @@ baseurl: "/docs/latest" # the subpath of your site, e.g. /blog url: "https://opensearch.org" # the base hostname & protocol for your site, e.g. http://example.com permalink: /:path/ -opensearch_version: '2.14.0' -opensearch_dashboards_version: '2.14.0' -opensearch_major_minor_version: '2.14' +opensearch_version: '2.15.0' +opensearch_dashboards_version: '2.15.0' +opensearch_major_minor_version: '2.15' lucene_version: '9_10_0' # Build settings diff --git a/_dashboards/csp/csp-dynamic-configuration.md b/_dashboards/csp/csp-dynamic-configuration.md index 729ebbdb5b..abe80a60c7 100644 --- a/_dashboards/csp/csp-dynamic-configuration.md +++ b/_dashboards/csp/csp-dynamic-configuration.md @@ -1,11 +1,11 @@ --- layout: default -title: Configuring the Content Security Policy `frame-ancestors` directive dynamically -nav_order: 110 +title: Configuring CSP rules for `frame-ancestors` +nav_order: 140 has_children: false --- -# Configuring the CSP `frame-ancestors` directive dynamically +# Configuring CSP rules for `frame-ancestors` Introduced 2.13 {: .label .label-purple } diff --git a/_dashboards/dashboards-assistant/index.md b/_dashboards/dashboards-assistant/index.md index d44e6b58e8..1c2f0f8299 100644 --- a/_dashboards/dashboards-assistant/index.md +++ b/_dashboards/dashboards-assistant/index.md @@ -19,14 +19,14 @@ The OpenSearch Assistant toolkit helps you create AI-powered assistants for Open To enable **OpenSearch Assistant** in OpenSearch Dashboards, locate your copy of the `opensearch_dashboards.yml` file and set the following option: -``` +```yaml assistant.chat.enabled: true ``` {% include copy-curl.html %} Then configure the root `agent_id` through the following API: -``` +```json PUT .plugins-ml-config/_doc/os_chat { "type":"os_chat_root_agent", @@ -37,6 +37,8 @@ PUT .plugins-ml-config/_doc/os_chat ``` {% include copy-curl.html %} +For more information about configuring the root agent, see the [Build your own chatbot tutorial]({{site.url}}{{site.baseurl}}/ml-commons-plugin/tutorials/build-chatbot/#step-5-configure-a-root-chatbot-agent-in-opensearch-dashboards). + This example shows a system index. In security-enabled domains, only super admins have permission to execute this code. For information about making super admin calls, see the [System indexes]({{site.url}}{{site.baseurl}}/security/configuration/system-indices/) guide. For access permission, contact your IT administrator. {: .warning} @@ -122,3 +124,4 @@ The following screenshot shows a saved conversation, along with actions you can - [Getting started guide for OpenSearch Assistant in OpenSearch Dashboards](https://github.com/opensearch-project/dashboards-assistant/blob/main/GETTING_STARTED_GUIDE.md) - [OpenSearch Assistant configuration through the REST API]({{site.url}}{{site.baseurl}}/ml-commons-plugin/opensearch-assistant/) +- [Build your own chatbot]({{site.url}}{{site.baseurl}}/ml-commons-plugin/tutorials/build-chatbot/) \ No newline at end of file diff --git a/_dashboards/management/multi-data-sources.md b/_dashboards/management/multi-data-sources.md index bed5b351c0..dc3096c251 100644 --- a/_dashboards/management/multi-data-sources.md +++ b/_dashboards/management/multi-data-sources.md @@ -7,15 +7,18 @@ redirect_from: - /dashboards/discover/multi-data-sources/ --- -# Configuring and using multiple data sources +# Configuring and using multiple data sources in OpenSearch Dashboards -You can ingest, process, and analyze data from multiple data sources in OpenSearch Dashboards. You configure the data sources in the **Dashboards Management** > **Data sources** app, as shown in the following image. +You can ingest, process, and analyze data from multiple data sources in OpenSearch Dashboards. You configure the data sources under **Dashboards Management** > **Data sources**. This interface is shown in the following image. -Dashboards Management Data sources main screen +Dashboards Management data sources main screen ## Getting started -The following tutorial guides you through configuring and using multiple data sources. +The following tutorial guides you through configuring and using multiple data sources in OpenSearch Dashboards. + +The following features are not supported when using multiple data sources: timeline visualization types and the `gantt-chart` plugin. +{: .note} ### Step 1: Modify the YAML file settings @@ -35,10 +38,10 @@ A data source connection specifies the parameters needed to connect to a data so To create a new data source connection: 1. From the OpenSearch Dashboards main menu, select **Dashboards Management** > **Data sources** > **Create data source connection**. - + 2. Add the required information to each field to configure the **Connection Details** and **Authentication Method**. - - Under **Connection Details**, enter a title and endpoint URL. For this tutorial, use the URL `http://localhost:5601/app/management/opensearch-dashboards/dataSources`. Entering a description is optional. + - Under **Connection Details**, enter a title and endpoint URL. For this tutorial, use the URL `https://localhost:9200/`. Entering a description is optional. - Under **Authentication Method**, select an authentication method from the dropdown list. Once an authentication method is selected, the applicable fields for that method appear. You can then enter the required details. The authentication method options are: - **No authentication**: No authentication is used to connect to the data source. @@ -51,22 +54,22 @@ To create a new data source connection: - After you have entered the appropriate details in all of the required fields, the **Test connection** and **Create data source** buttons become active. You can select **Test connection** to confirm that the connection is valid. -3. Select **Create data source** to save your settings. The connection is created, and the new data source appears in the list on the **Data Sources** main page. The first data source you create is marked as your default. +3. Select **Create data source** to save your settings. The connection is created, and the new data source appears in the list on the **Data Sources** main page. The first data source you create is marked as your default. 4. Edit or update a data source connection. - On the **Data Sources** main page, select the connection you want to modify. The **Connection Details** window opens. - - To mark the selected data source as the default, select the **Set as default** option. + - To mark the selected data source as the default, select the **Set as default** option. - To make changes to **Connection Details**, edit one or both of the **Title** and **Description** fields and select **Save changes** in the lower-right corner of the screen. You can also cancel changes here. To change the **Authentication Method**, choose a different authentication method, enter your credentials (if applicable), and then select **Save changes** in the lower-right corner of the screen. The changes are saved. - + - When **Username & Password** is the selected authentication method, you can update the password by choosing **Update stored password** next to the **Password** field. In the pop-up window, enter a new password in the first field and then enter it again in the second field to confirm. Select **Update stored password** in the pop-up window. The new password is saved. Select **Test connection** to confirm that the connection is valid. - When **AWS SigV4** is the selected authentication method, you can update the credentials by selecting **Update stored AWS credential**. In the pop-up window, enter a new access key in the first field and a new secret key in the second field. Select **Update stored AWS credential** in the pop-up window. The new credentials are saved. Select **Test connection** in the upper-right corner of the screen to confirm that the connection is valid. 5. Delete the data source connection by selecting the check box to the left of the title and then choosing **Delete 1 connection**. Selecting multiple check boxes for multiple connections is supported. Alternatively, select the {::nomarkdown}trash can icon{:/} icon. -An example data source connection screen is shown in the following image. +A data source connection interface is shown in the following image. Data source connection screen @@ -93,13 +96,15 @@ To select a data source through the Dev Tools console, follow these steps: 5. From the **Data source** dropdown menu, select a data source and then query the source. 6. Repeat the preceding steps for each data source you want to select. -### Upload saved objects to a dashboard from connected data sources +--- + +## Uploading saved objects to a dashboard from connected data sources To upload saved objects from connected data sources to a dashboard with multiple data sources, export them as an NDJSON file from the data source's **Saved object management** page. Then upload the file to the dashboard's **Saved object management** page. This method can simplify the transfer of saved objects between dashboards. The following 20-second video shows this feature in action. Multiple data sources in Saved object management{: .img-fluid} -#### Import saved objects from a connected data source +### Importing saved objects from a connected data source Follow these steps to import saved objects from a connected data source: @@ -109,11 +114,13 @@ Follow these steps to import saved objects from a connected data source: 4. Select **Import** > **Select file** and upload the file acquired from the connected data source. 5. Choose the appropriate **Data source** from the dropdown menu, set your **Conflict management** option, and then select the **Import** button. -### Show or hide authentication methods for multiple data sources +--- + +## Showing or hiding authentication methods Introduced 2.13 {: .label .label-purple } -A feature flag in your `opensearch_dashboards.yml` file allows you to show or hide authentication methods within the `data_source` plugin. The following example setting, shown in a 10-second demo, hides the authentication method for `AWSSigV4`. +A feature flag in your `opensearch_dashboards.yml` file allows you to show or hide authentication methods within the `data_source` plugin. The following setting hides the authentication method for `AWSSigV4`. ```` # Set enabled to false to hide the authentication method from multiple data source in OpenSearch Dashboards. @@ -128,89 +135,212 @@ data_source.authTypes: enabled: false ```` +The following demo shows this process. + Multiple data sources hide and show authentication{: .img-fluid} -### Hide the local cluster option for multiple data sources +## Showing or hiding the local cluster Introduced 2.13 {: .label .label-purple } -A feature flag in your `opensearch_dashboards.yml` file allows you to hide the local cluster option within the `data_source` plugin. This option hides the local cluster from the data source dropdown menu and index creation page, which is ideal for environments with or without a local OpenSearch cluster. The following example setting, shown in a 20-second demo, hides the local cluster. +A feature flag in your `opensearch_dashboards.yml` file allows you to hide the local cluster option within the `data_source` plugin. This option hides the local cluster from the data source dropdown menu and index creation page, which is ideal for environments with or without a local OpenSearch cluster. The following example setting, shown in a 20-second demo, hides the local cluster: ```` -# hide local cluster in the data source dropdown and index pattern creation page. +# hide local cluster in the data source dropdown and index pattern creation page. data_source.hideLocalCluster: true ```` +The following demo shows this process. + Multiple data sources hide local cluster{: .img-fluid} +--- + ## Using multiple data sources with external dashboards plugins Introduced 2.14 -{: .label .label-purple } +{: .label .label-purple} -The following plugins now support multiple data sources +The following plugins now support multiple data sources. ### Index management -When the data source feature is enabled, you can navigate to **Index Management** under the **Management** menu. Using indexes as an example, you can view all connected data sources and select a specific one from the navigation bar on the upper right. By default, the indexes from the designated default data source are displayed. However, you can select any connected data source to view its corresponding indexes. The following GIF illustrates these steps. +When you set `data_source.enabled:true`, you can view and select data sources and their associated indexes directly from the interface: + +1. Navigate to **Management** > **Index Management** under the main menu. +2. Select **Indexes** from the sidebar menu and then select the {::nomarkdown}database icon{:/} icon on the upper-right menu bar. +3. Choose the appropriate data source from the dropdown menu and then choose the appropriate index from the list. By default, the indexes from your default data source are displayed. You can choose any connected data source to view its corresponding indexes. + +The following GIF illustrates these steps. Multiple data sources in ISM list page -To perform operations on a specific index within a data source, select the individual index from the list. To create a new index, select the **Create Index** button, which opens a form. Fill in the required information and select the **Create** button. The index is created within the selected data source. The following GIF illustrates these steps. +To perform operations on a specific index within a data source, select the individual index from the list. To create a new index, select the **Create Index** button, which opens a form. Enter the required information and select the **Create** button. The index is created within the selected data source. The following GIF illustrates these steps. Multiple data sources in ISM create page ### Anomaly detection -When the data source feature is enabled, you can navigate to **Anomaly Detection** under the **OpenSearch Plugins** menu. On the navigation bar on the upper right, you can view all connected data sources and select a specific data source to view the dashboard from that source if it has detectors. If the selected data source does not have any detectors, the page prompts you to **Create detector**. The following GIF illustrates these steps. +When you set `data_source.enabled:true`, you can create or view detectors associated with a data source: + +1. Navigate to **OpenSearch Plugins** > **Anomaly Detection** under the main menu. +2. Select the database icon on the upper-right menu bar to view a list of connected data sources. +3. Select a data source to view a list of associated detectors. If the selected data source does not have detectors, then the **Create detector** button appears under the upper-right menu bar. See [Creating anomaly detectors]({{site.url}}{{site.baseurl}}/observing-your-data/ad/dashboards-anomaly-detection/#creating-anomaly-detectors) for instructions on creating detectors through the interface. + +The following GIF illustrates these steps. Multiple data sources in Anomaly Detection dashboard page -When you select **Detectors** from the side bar, the page displays the detectors currently configured for the selected data source. You can view and configure individual detectors by selecting them from the list. The following GIF illustrates these steps. +You can edit the data source's associated detectors on the **Detectors** tab under the left side bar. + +1. Select **Detectors** and then select the {::nomarkdown}database icon{:/} icon on the upper-right menu bar. +2. From the dropdown menu, select the appropriate data source. A list of associated detectors appears. +3. Choose a detector from the list, select **Actions**, and then choose the appropriate edit option from the dropdown menu. +4. Enter the applicable settings and configuration details. + +The following GIF illustrates these steps. Multiple data sources in Anomaly Detection detector page ### Security -When the data source feature is enabled, you can navigate to **Security** under the **Management** menu. Using role management as an example, you can view all connected data sources in the navigation bar on the upper right and select a specific data source to view its existing roles. To create a new role, select the **Create role** button, which takes you to a new page. Enter the required information and select **Create** to add the new role to the selected data source. The following GIF illustrates these steps. +When you set `data_source.enabled:true`, you can view and manage roles for each connected data source: + +1. Navigate to **Management** > **Security** under the main menu. +2. Select **Roles** from the left sidebar menu and then select the {::nomarkdown}database icon{:/} icon on the upper-right menu bar. +3. From the dropdown menu, select the appropriate data source and then select the **Create role** button to add a new role. +4. Enter the required configuration information and select the **Create** button to save. + +The following GIF illustrates these steps. Multiple data sources in Security plugin ### Maps -When the data source feature is enabled, you can navigate to **Maps** under the **OpenSearch Plugins** menu. To edit an existing map, select it from the maps list page, which opens the edit page. On the edit page, you can view all available data sources and the ones currently used in the map. To add a new layer, select **Add layer**, and then select **Documents** from the prompt, which opens a flyout. In the flyout, select the index pattern and geospatial field. Note that the data source name is prefixed to the index pattern name. After selecting **Update**, the new layer is added. Select the {::nomarkdown}database icon{:/} icon to verify that a new data source is now being used in the map. The following GIF illustrates these steps. +When you set `data_source.enabled:true`, you can view all available data sources, including the ones currently used as layers, in a map: + +1. Navigate to **OpenSearch Plugins** > **Maps** under the main menu. +2. From the dropdown menu, select the appropriate data source to edit or create an associated map layer: + - Edit a map layer by selecting one from the **Layers** dropdown menu. In the pop-up window, view the settings and edit them as needed. + - Add a new layer by selecting the **Add layer** button from the dropdown menu and then selecting **Documents** in the pop-up window. Another pop-up window appears on the right. Enter the required information on the **Data** tab. Note that the data source name is prefixed to the index pattern name. The **Style** and **Settings** tabs include optional information. + - Select **Update** to save the settings. +3. Select the **Save** button on the menu bar to save the edited or new layer. +4. Select the {::nomarkdown}database icon{:/} icon on the upper-right menu bar to verify that the new data source is listed in the dropdown menu. + +The following GIF illustrates these steps. Multiple data sources in Maps plugin ### Machine learning -When the data source feature is enabled, you can navigate to **Machine Learning** under the **OpenSearch Plugins** menu. Initially, the models within the default data source are displayed. To view models from a different data source, switch to that data source from the navigation bar. To inspect the details of a specific model, select the {::nomarkdown}inspect icon{:/} icon to the right of the model entry. The following GIF illustrates these steps. +When you set `data_source.enabled:true`, you can view and manage machine learning models from different connected data sources: + +1. Navigate to **OpenSearch Plugins** > **Machine Learning** under the main menu. +2. Select the {::nomarkdown}database icon{:/} icon and choose a data source from the dropdown menu. A list of models associated with the selected data source is displayed. +3. Select the {::nomarkdown}inspect icon{:/} icon to the right of a listed model to view the model's configuration details for the selected data source. + +The following GIF illustrates these steps. Multiple data sources in Machine Learning Plugin ### Notifications -When the data source feature is enabled, you can navigate to **Notifications** under the **Management** menu. The page displays the notification channels configured for the currently selected data source. To view channels from a different data source, select the desired data source from the menu. To view or edit the details of an existing channel, select it from the list, which opens the channel details page. The following GIF illustrates these steps. +When you set `data_source.enabled:true`, you can view and manage notification channels for different data sources: + +1. Navigate to **Management** > **Notifications** under the main menu. +2. Select the {::nomarkdown}database icon{:/} icon and choose a data source from the dropdown menu. A list of channels associated with the selected data source is displayed. +3. Choose a channel from the list to view or manage its settings. + - Edit the channel's settings by selecting the **Actions** button and choosing the **Edit** option. Enter the required information in the **Edit channel** panel and then choose **Save**. + - Send a test message to the channel by selecting the **Send test message** button in the **Edit channel** window. Alternatively, you can select the **Actions** button in the channel details window and then choose the **Send test message** option from the dropdown menu. + +The following GIF illustrates these steps. Multiple data sources in Notification plugin ### Search relevance -When the data source feature is enabled, you can navigate to **Search Relevance** under the **OpenSearch Plugins** menu. On the navigation bar on the upper right, you can view all available data sources. To compare search results between indexes from different data sources, first select a data source and an index for **Query 1**, and then select a data source and an index for **Query 2**. Select **Search** to run the queries. The following GIF illustrates these steps. +When you set `data_source.enabled:true`, you can compare search results across indexes from different data sources: + +1. Navigate to **OpenSearch Plugins** > **Search Relevance** under the main menu. +2. Select the {::nomarkdown}database icon{:/} icon and choose a data source from the dropdown menu. A list of available data sources is displayed. +3. Under both **Query 1** and **Query 2**, select a data source and an index. +4. Select the **Search** button to run the queries. The query results are displayed in their respective results panels. + +The following GIF illustrates these steps. Multiple data sources in Search Relevance plugin -## Next steps +### Security analytics +Introduced 2.15 +{: .label .label-purple} + +When you set `data_source.enabled:true`, you can view and manage security analytics resources, such as detection rules, across multiple connected data sources: + +1. Navigate to **OpenSearch Plugins** > **Security analytics** under the main menu. +2. Select the {::nomarkdown}database icon{:/} icon and choose a data source from the dropdown menu. +3. Select **Dectectors** > **Detection rules** from the navigation menu on the left. A list of detection rules is displayed. +4. Select a rule to open a pop-up window containing more information about that rule. + +The following GIF illustrates these steps. + +Multiple data sources in Security analytics list page + +1. Navigate to **OpenSearch Plugins** > **Security analytics** under the main menu. +2. Select the {::nomarkdown}database icon{:/} icon and choose a data source from the dropdown menu. +3. Select **Dectectors** > **Detection rules** from the navigation menu on the left. +4. Select the **Create detection rule** button on the upper right and then enter the required configuration details in the **Create detection rule** window. +5. Select the **Create detection rule** button on the lower right to save the rule. The rule is now associated with the data source. + +The following GIF illustrates these steps. + +Multiple data sources in Security analytics create page + +### Alerting +Introduced 2.15 +{: .label .label-purple } + +When you set `data_source.enabled:true`, you can you can view and manage alerting monitors across multiple connected data sources: + +1. Navigate to **OpenSearch Plugins** > **Alerting** under the main menu. +2. Select the {::nomarkdown}database icon{:/} icon and choose a data source from the dropdown menu. A list of associated monitors is displayed. +3. Select a monitor to view its details. -After configuring multiple data sources, you can analyze the data from each source. Refer to the following resources for more information: +The following GIF illustrates these steps. -- Learn about [managing index patterns]({{site.url}}{{site.baseurl}}/dashboards/management/index-patterns/) through OpenSearch Dashboards. -- Learn about [indexing data using Index Management]({{site.url}}{{site.baseurl}}/dashboards/im-dashboards/index/) through OpenSearch Dashboards. -- Learn about how to [connect OpenSearch and Amazon S3 through OpenSearch Dashboards]({{site.url}}{{site.baseurl}}/dashboards/management/S3-data-source/). -- Learn about the [Integrations tool]({{site.url}}{{site.baseurl}}/integrations/index/), which gives you the flexibility to use various data ingestion methods and connect data from the Dashboards UI. +Multiple data sources in Alerting list page + +To create a new monitor, select **Create monitor**. Fill out the form and select **Create**. The monitor is created within the selected data source. + +#### Managing alerting monitors from within the Dashboards application + +To manage data source monitors from within **Dashboards**: + +1. Navigate to the **Dashboards** application under the main menu and then select a dashboard from the list. +2. From the dashboard, select the {::nomarkdown}ellipsis icon{:/} icon to open the **Options** dropdown menu and then choose **Alerting**. +4. From the **Alerting** dropdown menu, choose **Associated monitors** to open the configuration window. +5. Select a monitor from the list to view or edit its details. + +The following GIF illustrates these steps. + +Multiple data sources with Feature anywhere associated monitor + +To associate a monitor with a data source: + +1. Navigate to the **Dashboards** application under the main menu and then select a dashboard from the list. +2. From the dashboard, select the {::nomarkdown}ellipsis icon{:/} icon to open the **Options** dropdown menu and then choose **Alerting**. +3. From the **Alerting** dropdown menu, choose **Add alerting monitor** to open the configuration window. +4. Enter the configuration information and then select the **Create monitor** button. The monitor is now associated with the data source. + +The following GIF illustrates these steps. + +Multiple data sources with Feature anywhere add associated monitor + +--- -## Limitations +## Next steps -The following features are not supported when using multiple data sources: +After configuring multiple data sources, you can analyze the data from each source. See the following resources for more information: -* Timeline visualization types -* Some external plugins, such as the `gantt-chart` plugin +- [Index patterns]({{site.url}}{{site.baseurl}}/dashboards/management/index-patterns/) +- [Index Management]({{site.url}}{{site.baseurl}}/dashboards/im-dashboards/index/) +- [Connecting OpenSearch and Amazon S3 through OpenSearch Dashboards]({{site.url}}{{site.baseurl}}/dashboards/management/S3-data-source/) +- [OpenSearch Integrations]({{site.url}}{{site.baseurl}}/integrations/index/) diff --git a/_dashboards/quickstart.md b/_dashboards/quickstart.md index 358efe4003..82a2b446a5 100644 --- a/_dashboards/quickstart.md +++ b/_dashboards/quickstart.md @@ -4,7 +4,8 @@ title: OpenSearch Dashboards quickstart guide nav_order: 2 has_children: false redirect_from: - - /dashboards/quickstart-dashboards/ + - /dashboards/get-started/quickstart-dashboards/ + - /dashboards/quickstart-dashboards/ --- # OpenSearch Dashboards quickstart guide diff --git a/_dashboards/visualize/maps.md b/_dashboards/visualize/maps.md index 8a4196e483..23e14d41c3 100644 --- a/_dashboards/visualize/maps.md +++ b/_dashboards/visualize/maps.md @@ -5,6 +5,8 @@ grand_parent: Building data visualizations parent: Using coordinate and region maps nav_order: 10 redirect_from: + - /dashboards/maps-plugin/ + - /dashboards/visualize/maps/ - /dashboards/maps/ --- diff --git a/_dashboards/visualize/visbuilder.md b/_dashboards/visualize/visbuilder.md index 7b32e818f5..de4dfb1666 100644 --- a/_dashboards/visualize/visbuilder.md +++ b/_dashboards/visualize/visbuilder.md @@ -9,9 +9,6 @@ redirect_from: # Using VisBuilder -VisBuilder is an experimental feature and shouldn't be used in a production environment. For updates on its progress, or if you want to leave feedback that helps improve the feature, see the [GitHub issue](https://github.com/opensearch-project/OpenSearch-Dashboards/issues/2280). -{: .warning} - You can use the VisBuilder visualization type in OpenSearch Dashboards to create data visualizations by using a drag-and-drop gesture. With VisBuilder you have: * An immediate view of your data without the need to preselect the visualization output. @@ -22,36 +19,22 @@ You can use the VisBuilder visualization type in OpenSearch Dashboards to create ## Try VisBuilder in the OpenSearch Dashboards playground -If you'd like to try out VisBuilder without installing OpenSearch locally, you can do so in the [Dashboards playground](https://playground.opensearch.org/app/vis-builder#/). VisBuilder is enabled by default. +If you'd like to try out VisBuilder without installing OpenSearch locally, you can do so in the [Dashboards playground](https://playground.opensearch.org/app/vis-builder#/). ## Try VisBuilder locally -VisBuilder is enabled by default. If you want to disable it, set the feature `flag vis_builder.enabled:` to `false` in the `opensearch_dashboards.yml` file as follows: - -``` -# Set the value of this setting to false to disable VisBuilder -# functionality in Visualization. -vis_builder.enabled: false -``` - Follow these steps to create a new visualization using VisBuilder in your environment: 1. Open Dashboards: - If you're not running the Security plugin, go to http://localhost:5601. - If you're running the Security plugin, go to https://localhost:5601 and log in with your username and password (default is admin/admin). -2. Confirm that the **Enable experimental visualizations** option is turned on. - - From the top menu, select **Management** > **Dashboards Management** > **Advanced Settings**. - - Select **Visualization** and verify that the option is turned on. - - Enable experimental visualizations - -3. From the top menu, select **Visualize** **>** **Create visualization** **>** **VisBuilder**. +1. From the top menu, select **Visualize > Create visualization > VisBuilder**. Select the VisBuilder visualization type -4. Drag and drop field names from the left column into the **Configuration** panel to generate a visualization. +1. Drag and drop field names from the left column into the **Configuration** panel to generate a visualization. Here’s an example visualization. Your visualization will look different depending on your data and the fields you select. -Visualization generated using sample data +Visualization generated using sample data \ No newline at end of file diff --git a/_data-prepper/common-use-cases/codec-processor-combinations.md b/_data-prepper/common-use-cases/codec-processor-combinations.md index 57185f2ce9..525bc704be 100644 --- a/_data-prepper/common-use-cases/codec-processor-combinations.md +++ b/_data-prepper/common-use-cases/codec-processor-combinations.md @@ -45,3 +45,6 @@ The [`newline` codec]({{site.url}}{{site.baseurl}}/data-prepper/pipelines/config [Apache Avro] helps streamline streaming data pipelines. It is most efficient when used with the [`avro` codec]({{site.url}}{{site.baseurl}}/data-prepper/pipelines/configuration/sinks/s3#avro-codec) inside an `s3` sink. +## `event_json` + +The `event_json` output codec converts event data and metadata into JSON format to send to a sink, such as an S3 sink. The `event_json` input codec reads the event and its metadata to create an event in Data Prepper. diff --git a/_data-prepper/migrate-open-distro.md b/_data-prepper/migrate-open-distro.md index e7fdacbd8f..8b3e7a7198 100644 --- a/_data-prepper/migrate-open-distro.md +++ b/_data-prepper/migrate-open-distro.md @@ -2,6 +2,8 @@ layout: default title: Migrating from Open Distro nav_order: 30 +redirect_from: + - /clients/data-prepper/migrate-open-distro/ --- # Migrating from Open Distro diff --git a/_data-prepper/migrating-from-logstash-data-prepper.md b/_data-prepper/migrating-from-logstash-data-prepper.md index f87ca8d6be..3d87f29517 100644 --- a/_data-prepper/migrating-from-logstash-data-prepper.md +++ b/_data-prepper/migrating-from-logstash-data-prepper.md @@ -3,6 +3,7 @@ layout: default title: Migrating from Logstash nav_order: 25 redirect_from: + - /clients/data-prepper/configure-logstash-data-prepper/ - /data-prepper/configure-logstash-data-prepper/ --- diff --git a/_data-prepper/pipelines/configuration/processors/aggregate.md b/_data-prepper/pipelines/configuration/processors/aggregate.md index 699d25025f..38b138a996 100644 --- a/_data-prepper/pipelines/configuration/processors/aggregate.md +++ b/_data-prepper/pipelines/configuration/processors/aggregate.md @@ -20,6 +20,7 @@ Option | Required | Type | Description identification_keys | Yes | List | An unordered list by which to group events. Events with the same values as these keys are put into the same group. If an event does not contain one of the `identification_keys`, then the value of that key is considered to be equal to `null`. At least one identification_key is required (for example, `["sourceIp", "destinationIp", "port"]`). action | Yes | AggregateAction | The action to be performed on each group. One of the [available aggregate actions](#available-aggregate-actions) must be provided, or you can create custom aggregate actions. `remove_duplicates` and `put_all` are the available actions. For more information, see [Creating New Aggregate Actions](https://github.com/opensearch-project/data-prepper/tree/main/data-prepper-plugins/aggregate-processor#creating-new-aggregate-actions). group_duration | No | String | The amount of time that a group should exist before it is concluded automatically. Supports ISO_8601 notation strings ("PT20.345S", "PT15M", etc.) as well as simple notation for seconds (`"60s"`) and milliseconds (`"1500ms"`). Default value is `180s`. +local_mode | No | Boolean | When `local_mode` is set to `true`, the aggregation is performed locally on each Data Prepper node instead of forwarding events to a specific node based on the `identification_keys` using a hash function. Default is `false`. ## Available aggregate actions @@ -176,4 +177,4 @@ The `aggregate` processor includes the following custom metrics. **Gauge** -* `currentAggregateGroups`: The current number of groups. This gauge decreases when a group concludes and increases when an event initiates the creation of a new group. \ No newline at end of file +* `currentAggregateGroups`: This gauge represents the current number of active aggregate groups. It decreases when an aggregate group is completed and its results are emitted and increases when a new event initiates the creation of a new aggregate group. diff --git a/_data-prepper/pipelines/configuration/processors/key-value.md b/_data-prepper/pipelines/configuration/processors/key-value.md index 884ae97549..aedc1f8822 100644 --- a/_data-prepper/pipelines/configuration/processors/key-value.md +++ b/_data-prepper/pipelines/configuration/processors/key-value.md @@ -33,6 +33,11 @@ You can use the `key_value` processor to parse the specified field into key-valu | recursive | Specifies whether to recursively obtain additional key-value pairs from values. The extra key-value pairs will be stored as sub-keys of the root key. Default is `false`. The levels of recursive parsing must be defined by different brackets for each level: `[]`, `()`, and `<>`, in this order. Any other configurations specified will only be applied to the outmost keys.
When `recursive` is `true`:
`remove_brackets` cannot also be `true`;
`skip_duplicate_values` will always be `true`;
`whitespace` will always be `"strict"`. | If `recursive` is true, `{"item1=[item1-subitem1=item1-subitem1-value&item1-subitem2=(item1-subitem2-subitem2A=item1-subitem2-subitem2A-value&item1-subitem2-subitem2B=item1-subitem2-subitem2B-value)]&item2=item2-value"}` will parse into `{"item1": {"item1-subitem1": "item1-subitem1-value", "item1-subitem2" {"item1-subitem2-subitem2A": "item1-subitem2-subitem2A-value", "item1-subitem2-subitem2B": "item1-subitem2-subitem2B-value"}}}`. | | overwrite_if_destination_exists | Specifies whether to overwrite existing fields if there are key conflicts when writing parsed fields to the event. Default is `true`. | If `overwrite_if_destination_exists` is `true` and destination is `null`, `{"key1": "old_value", "message": "key1=new_value"}` will parse into `{"key1": "new_value", "message": "key1=new_value"}`. | | tags_on_failure | When a `kv` operation causes a runtime exception within the processor, the operation is safely stopped without crashing the processor, and the event is tagged with the provided tags. | If `tags_on_failure` is set to `["keyvalueprocessor_failure"]`, `{"tags": ["keyvalueprocessor_failure"]}` will be added to the event's metadata in the event of a runtime exception. | +| value_grouping | Specifies whether to group values using predefined value grouping delimiters: `{...}`, `[...]', `<...>`, `(...)`, `"..."`, `'...'`, `http://... (space)`, and `https:// (space)`. If this flag is enabled, then the content between the delimiters is considered to be one entity and is not parsed for key-value pairs. Default is `false`. If `value_grouping` is `true`, then `{"key1=[a=b,c=d]&key2=value2"}` parses to `{"key1": "[a=b,c=d]", "key2": "value2"}`. | +| drop_keys_with_no_value | Specifies whether keys should be dropped if they have a null value. Default is `false`. If `drop_keys_with_no_value` is set to `true`, then `{"key1=value1&key2"}` parses to `{"key1": "value1"}`. | +| strict_grouping | Specifies whether strict grouping should be enabled when the `value_grouping` or `string_literal_character` options are used. Default is `false`. | When enabled, groups with unmatched end characters yield errors. The event is ignored after the errors are logged. | +| string_literal_character | Can be set to either a single quotation mark (`'`) or a double quotation mark (`"`). Default is `null`. | When this option is used, any text contained within the specified quotation mark character will be ignored and excluded from key-value parsing. For example, `text1 "key1=value1" text2 key2=value2` would parse to `{"key2": "value2"}`. | +| key_value_when | Allows you to specify a [conditional expression](https://opensearch.org/docs/latest/data-prepper/pipelines/expression-syntax/), such as `/some-key == "test"`, that will be evaluated to determine whether the processor should be applied to the event. | @@ -42,4 +47,4 @@ Content will be added to this section. ## Metrics -Content will be added to this section. ---> \ No newline at end of file +Content will be added to this section. ---> diff --git a/_data-prepper/pipelines/configuration/processors/obfuscate.md b/_data-prepper/pipelines/configuration/processors/obfuscate.md index 13d906acb3..8d6bf901da 100644 --- a/_data-prepper/pipelines/configuration/processors/obfuscate.md +++ b/_data-prepper/pipelines/configuration/processors/obfuscate.md @@ -67,6 +67,7 @@ Use the following configuration options with the `obfuscate` processor. | `source` | Yes | The source field to obfuscate. | | `target` | No | The new field in which to store the obfuscated value. This leaves the original source field unchanged. When no `target` is provided, the source field updates with the obfuscated value. | | `patterns` | No | A list of regex patterns that allow you to obfuscate specific parts of a field. Only parts that match the regex pattern will obfuscate. When not provided, the processor obfuscates the whole field. | +| `single_word_only` | No | When set to `true`, a word boundary `\b` is added to the pattern, which causes obfuscation to be applied only to words that are standalone in the input text. By default, it is `false`, meaning obfuscation patterns are applied to all occurrences. Can be used for Data Prepper 2.8 or greater. | `obfuscate_when` | No | Specifies under what condition the Obfuscate processor should perform matching. Default is no condition. | | `tags_on_match_failure` | No | The tag to add to an event if the obfuscate processor fails to match the pattern. | | `action` | No | The obfuscation action. As of Data Prepper 2.3, only the `mask` action is supported. | diff --git a/_data-prepper/pipelines/configuration/processors/write_json.md b/_data-prepper/pipelines/configuration/processors/write_json.md new file mode 100644 index 0000000000..9e94176010 --- /dev/null +++ b/_data-prepper/pipelines/configuration/processors/write_json.md @@ -0,0 +1,18 @@ +--- +layout: default +title: write_json +parent: Processors +grand_parent: Pipelines +nav_order: 56 +--- + +# write_json + + +The `write_json` processor converts an object in an event into a JSON string. You can customize the processor to choose the source and target field names. + +| Option | Description | Example | +| :--- | :--- | :--- | +| source | Mandatory field that specifies the name of the field in the event containing the message or object to be parsed. | If `source` is set to `"message"` and the input is `{"message": {"key1":"value1", "key2":{"key3":"value3"}}`, then the `write_json` processor generates `{"message": "{\"key1\":\"value`\", \"key2\":"{\"key3\":\"value3\"}"}"`. +| target | An optional field that specifies the name of the field in which the resulting JSON string should be stored. If `target` is not specified, then the `source` field is used. + diff --git a/_data-prepper/pipelines/configuration/sinks/opensearch.md b/_data-prepper/pipelines/configuration/sinks/opensearch.md index c93f4708d1..b1c32f0005 100644 --- a/_data-prepper/pipelines/configuration/sinks/opensearch.md +++ b/_data-prepper/pipelines/configuration/sinks/opensearch.md @@ -65,7 +65,7 @@ Option | Required | Type | Description `connect_timeout` | No | Integer| The timeout value, in milliseconds, when requesting a connection from the connection manager. A timeout value of `0` is interpreted as an infinite timeout. If this timeout value is negative or not set, the underlying Apache HttpClient will rely on operating system settings to manage connection timeouts. `insecure` | No | Boolean | Whether or not to verify SSL certificates. If set to `true`, then certificate authority (CA) certificate verification is disabled and insecure HTTP requests are sent instead. Default is `false`. `proxy` | No | String | The address of the [forward HTTP proxy server](https://en.wikipedia.org/wiki/Proxy_server). The format is `"<hostname or IP>:<port>"` (for example, `"example.com:8100"`, `"http://example.com:8100"`, `"112.112.112.112:8100"`). The port number cannot be omitted. -`index` | Conditionally | String | The name of the export index. Only required when the `index_type` is `custom`. The index can be a plain string, such as `my-index-name`, contain [Java date-time patterns](https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html), such as `my-index-${yyyy.MM.dd}` or `my-${yyyy-MM-dd-HH}-index`, be formatted using field values, such as `my-index-${/my_field}`, or use [Data Prepper expressions](https://opensearch.org/docs/latest/data-prepper/pipelines/expression-syntax/), such as `my-index-${getMetadata(\"my_metadata_field\"}`. All formatting options can be combined to provide flexibility when creating static, dynamic, and rolling indexes. +`index` | Conditionally | String | The name of the export index. Only required when the `index_type` is `custom`. The index can be a plain string, such as `my-index-name`, contain [Java date-time patterns](https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html), such as `my-index-%{yyyy.MM.dd}` or `my-%{yyyy-MM-dd-HH}-index`, be formatted using field values, such as `my-index-${/my_field}`, or use [Data Prepper expressions](https://opensearch.org/docs/latest/data-prepper/pipelines/expression-syntax/), such as `my-index-${getMetadata(\"my_metadata_field\"}`. All formatting options can be combined to provide flexibility when creating static, dynamic, and rolling indexes. `index_type` | No | String | Tells the sink plugin what type of data it is handling. Valid values are `custom`, `trace-analytics-raw`, `trace-analytics-service-map`, or `management-disabled`. Default is `custom`. `template_type` | No | String | Defines what type of OpenSearch template to use. Available options are `v1` and `index-template`. The default value is `v1`, which uses the original OpenSearch templates available at the `_template` API endpoints. The `index-template` option uses composable [index templates]({{site.url}}{{site.baseurl}}/opensearch/index-templates/), which are available through the OpenSearch `_index_template` API. Composable index types offer more flexibility than the default and are necessary when an OpenSearch cluster contains existing index templates. Composable templates are available for all versions of OpenSearch and some later versions of Elasticsearch. When `distribution_version` is set to `es6`, Data Prepper enforces the `template_type` as `v1`. `template_file` | No | String | The path to a JSON [index template]({{site.url}}{{site.baseurl}}/opensearch/index-templates/) file, such as `/your/local/template-file.json`, when `index_type` is set to `custom`. For an example template file, see [otel-v1-apm-span-index-template.json](https://github.com/opensearch-project/data-prepper/blob/main/data-prepper-plugins/opensearch/src/main/resources/otel-v1-apm-span-index-template.json). If you supply a template file, then it must match the template format specified by the `template_type` parameter. diff --git a/_data-prepper/pipelines/configuration/sinks/s3.md b/_data-prepper/pipelines/configuration/sinks/s3.md index 71cb7b1f70..d1413f6ffc 100644 --- a/_data-prepper/pipelines/configuration/sinks/s3.md +++ b/_data-prepper/pipelines/configuration/sinks/s3.md @@ -15,19 +15,20 @@ The `s3` sink uses the following format when batching events: ``` ${pathPrefix}events-%{yyyy-MM-dd'T'HH-mm-ss'Z'}-${currentTimeInNanos}-${uniquenessId}.${codecSuppliedExtension} ``` +{% include copy-curl.html %} -When a batch of objects is written to S3, the objects are formatted similarly to the following: +When a batch of objects is written to Amazon S3, the objects are formatted similarly to the following: ``` my-logs/2023/06/09/06/events-2023-06-09T06-00-01-1686290401871214927-ae15b8fa-512a-59c2-b917-295a0eff97c8.json ``` +{% include copy-curl.html %} - -For more information about how to configure an object, see the [Object key](#object-key-configuration) section. +For more information about how to configure an object, refer to [Object key](#object-key-configuration). ## Usage -The following example creates a pipeline configured with an s3 sink. It contains additional options for customizing the event and size thresholds for which the pipeline sends record events and sets the codec type `ndjson`: +The following example creates a pipeline configured with an `s3` sink. It contains additional options for customizing the event and size thresholds for the pipeline and sets the codec type as `ndjson`: ``` pipeline: @@ -49,10 +50,11 @@ pipeline: ndjson: buffer_type: in_memory ``` +{% include copy-curl.html %} ## IAM permissions -In order to use the `s3` sink, configure AWS Identity and Access Management (IAM) to grant Data Prepper permissions to write to Amazon S3. You can use a configuration similar to the following JSON configuration: +To use the `s3` sink, configure AWS Identity and Access Management (IAM) to grant Data Prepper permissions to write to Amazon S3. You can use a configuration similar to the following JSON configuration: ```json { @@ -69,36 +71,62 @@ In order to use the `s3` sink, configure AWS Identity and Access Management (IAM ] } ``` +{% include copy-curl.html %} + +## Cross-account S3 access + +When Data Prepper fetches data from an S3 bucket, it verifies bucket ownership using a [bucket owner condition](https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucket-owner-condition.html). + +By default, the S3 sink does not require `bucket_owners`. If `bucket_owners` is configured and a bucket is not included in one of the mapped configurations, `default_bucket_owner` defaults to the account ID in `aws.sts_role_arn`. You can configure both `bucket_owners` and `default_bucket_owner` and apply the settings together. + +When ingesting data from multiple S3 buckets with different account associations, configure Data Prepper for cross-account S3 access based on the following conditions: + +- For S3 buckets belonging to the same account, set `default_bucket_owner` to that account's ID. +- For S3 buckets belonging to multiple accounts, use a `bucket_owners` map. + +A `bucket_owners` map specifies account IDs for buckets belonging to multiple accounts. For example, in the following configuration, `my-bucket-01` is owned by `123456789012` and `my-bucket-02` is owned by `999999999999`: + +``` +sink: + - s3: + default_bucket_owner: 111111111111 + bucket_owners: + my-bucket-01: 123456789012 + my-bucket-02: 999999999999 +``` +{% include copy-curl.html %} ## Configuration Use the following options when customizing the `s3` sink. -Option | Required | Type | Description -:--- | :--- | :--- | :--- -`bucket` | Yes | String | The name of the S3 bucket to which objects are stored. The `name` must match the name of your object store. -`codec` | Yes | [Codec](#codec) | The codec determining the format of output data. -`aws` | Yes | AWS | The AWS configuration. See [aws](#aws) for more information. -`threshold` | Yes | [Threshold](#threshold-configuration) | Configures when to write an object to S3. -`object_key` | No | Sets the `path_prefix` and the `file_pattern` of the object store. The file pattern is always `events-%{yyyy-MM-dd'T'hh-mm-ss}`. By default, those objects are found inside the root directory of the bucket. The `path_prefix` is configurable. -`compression` | No | String | The compression algorithm to apply: `none`, `gzip`, or `snappy`. Default is `none`. -`buffer_type` | No | [Buffer type](#buffer-type) | Determines the buffer type. -`max_retries` | No | Integer | The maximum number of times a single request should retry when ingesting data to S3. Defaults to `5`. - -## aws +Option | Required | Type | Description +:--- |:---------|:------------------------------------------------| :--- +`bucket` | Yes | String | Specifies the sink's S3 bucket name. Supports dynamic bucket naming using [Data Prepper expressions]({{site.url}}{{site.baseurl}}/data-prepper/pipelines/expression-syntax/), for example, `test-${/bucket_id}`. If a dynamic bucket is inaccessible and no `default_bucket` is configured, then the object data is dropped. +`default_bucket` | No | String | A static bucket for inaccessible dynamic buckets in `bucket`. +`bucket_owners` | No | Map | A map of bucket names and their account owner IDs for cross-account access. Refer to [Cross-account S3 access](#s3_bucket_ownership). +`default_bucket_owner` | No | String | The AWS account ID for an S3 bucket owner. Refer to [Cross-account S3 access](#s3_bucket_ownership). +`codec` | Yes | [Codec](#codec) | Serializes data in S3 objects. +`aws` | Yes | AWS | The AWS configuration. Refer to [aws](#aws). +`threshold` | Yes | [Threshold](#threshold-configuration) | Condition for writing objects to S3. +`aggregate_threshold` | No | [Aggregate threshold](#threshold-configuration) | A condition for flushing objects with a dynamic `path_prefix`. +`object_key` | No | [Object key](#object-key-configuration) | Sets `path_prefix` and `file_pattern` for object storage. The file pattern is `events-%{yyyy-MM-dd'T'hh-mm-ss}`. By default, these objects are found in the bucket's root directory. `path_prefix` is configurable. +`compression` | No | String | The compression algorithm: Either `none`, `gzip`, or `snappy`. Default is `none`. +`buffer_type` | No | [Buffer type](#buffer-type) | The buffer type configuration. +`max_retries` | No | Integer | The maximum number of retries for S3 ingestion requests. Default is `5`. + +## `aws` Option | Required | Type | Description :--- | :--- | :--- | :--- `region` | No | String | The AWS Region to use for credentials. Defaults to [standard SDK behavior to determine the Region](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/region-selection.html). -`sts_role_arn` | No | String | The AWS Security Token Service (AWS STS) role to assume for requests to Amazon SQS and Amazon S3. Defaults to `null`, which will use the [standard SDK behavior for credentials](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/credentials.html). +`sts_role_arn` | No | String | The AWS Security Token Service (AWS STS) role to assume for requests to Amazon Simple Queue Service (Amazon SQS) and Amazon S3. Defaults to `null`, which uses the [standard SDK behavior for credentials](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/credentials.html). `sts_header_overrides` | No | Map | A map of header overrides that the IAM role assumes for the sink plugin. -`sts_external_id` | No | String | An STS external ID used when Data Prepper assumes the role. For more information, see the `ExternalId` documentation in the [STS AssumeRole](https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html) API reference. - - +`sts_external_id` | No | String | An AWS STS external ID used when Data Prepper assumes the role. For more information, refer to the `ExternalId` section under [AssumeRole](https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html) in the AWS STS API reference. ## Threshold configuration -Use the following options to set ingestion thresholds for the `s3` sink. When any of these conditions are met, Data Prepper will write events to an S3 object. +Use the following options to set ingestion thresholds for the `s3` sink. Data Prepper writes events to an S3 object when any of these conditions occur. Option | Required | Type | Description :--- | :--- | :--- | :--- @@ -106,84 +134,77 @@ Option | Required | Type | Description `maximum_size` | No | String | The maximum number of bytes to accumulate before writing an object to S3. Default is `50mb`. `event_collect_timeout` | Yes | String | The maximum amount of time before Data Prepper writes an event to S3. The value should be either an ISO-8601 duration, such as `PT2M30S`, or a simple notation, such as `60s` or `1500ms`. +## Aggregate threshold configuration + +Use the following options to set rules or limits that trigger certain actions or behavior when an aggregated value crosses a defined threshold. + +Option | Required | Type | Description +:--- |:-----------------------------------|:-------| :--- +`flush_capacity_ratio` | No | Float | The percentage of groups to be force-flushed when `aggregate_threshold maximum_size` is reached. The percentage is expressed as a number between `0.0` and `1.0`. Default is `0.5`. +`maximum_size` | Yes | String | The maximum number of bytes to accumulate before force-flushing objects. For example, `128mb`. ## Buffer type -`buffer_type` is an optional configuration that determines how Data Prepper temporarily stores data before writing an object to S3. The default value is `in_memory`. Use one of the following options: +`buffer_type` is an optional configuration that determines how Data Prepper temporarily stores data before writing an object to S3. The default value is `in_memory`. + +Use one of the following options: - `in_memory`: Stores the record in memory. -- `local_file`: Flushes the record into a file on your local machine. This uses your machine's temporary directory. +- `local_file`: Flushes the record into a file on your local machine. This option uses your machine's temporary directory. - `multipart`: Writes using the [S3 multipart upload](https://docs.aws.amazon.com/AmazonS3/latest/userguide/mpuoverview.html). Every 10 MB is written as a part. ## Object key configuration +Use the following options to define how object keys are constructed for objects stored in S3. + Option | Required | Type | Description :--- | :--- | :--- | :--- -`path_prefix` | No | String | The S3 key prefix path to use for objects written to S3. Accepts date-time formatting. For example, you can use `%{yyyy}/%{MM}/%{dd}/%{HH}/` to create hourly folders in S3. The prefix path should end with `/`. By default, Data Prepper writes objects to the root of the S3 bucket. - +`path_prefix` | No | String | The S3 key prefix path to use for objects written to S3. Accepts date-time formatting and dynamic injection of values using [Data Prepper expressions](https://opensearch.org/docs/latest/data-prepper/pipelines/expression-syntax/). For example, you can use `/${/my_partition_key}/%{yyyy}/%{MM}/%{dd}/%{HH}/` to create hourly folders in S3 based on the `my_partition_key` value. The prefix path should end with `/`. By default, Data Prepper writes objects to the S3 bucket root. -## codec +## `codec` The `codec` determines how the `s3` source formats data written to each S3 object. -### avro codec +### `avro` codec -The `avro` codec writes an event as an [Apache Avro](https://avro.apache.org/) document. +The `avro` codec writes an event as an [Apache Avro](https://avro.apache.org/) document. Because Avro requires a schema, you may either define the schema or have Data Prepper automatically generate it. Defining your own schema is recommended because this will allow it to be tailored to your particular use case. -Because Avro requires a schema, you may either define the schema yourself, or Data Prepper will automatically generate a schema. -In general, you should define your own schema because it will most accurately reflect your needs. +When you provide your own Avro schema, that schema defines the final structure of your data. Any extra values in any incoming events that are not mapped in the Avro schema will not be included in the final destination. Data Prepper does not allow the use of `include_keys` or `exclude_keys` with a custom schema so as to avoid confusion between a custom Avro schema and the `include_keys` or `exclude_keys` sink configurations. -We recommend that you make your Avro fields use a null [union](https://avro.apache.org/docs/current/specification/#unions). -Without the null union, each field must be present or the data will fail to write to the sink. -If you can be certain that each each event has a given field, you can make it non-nullable. +In cases where your data is uniform, you may be able to automatically generate a schema. Automatically generated schemas are based on the first event that the codec receives. The schema will only contain keys from this event, and all keys must be present in all events in order to automatically generate a working schema. Automatically generated schemas make all fields nullable. Use the `include_keys` and `exclude_keys` sink configurations to control which data is included in the automatically generated schema. -When you provide your own Avro schema, that schema defines the final structure of your data. -Therefore, any extra values inside any incoming events that are not mapped in the Arvo schema will not be included in the final destination. -To avoid confusion between a custom Arvo schema and the `include_keys` or `exclude_keys` sink configurations, Data Prepper does not allow the use of the `include_keys` or `exclude_keys` with a custom schema. - -In cases where your data is uniform, you may be able to automatically generate a schema. -Automatically generated schemas are based on the first event received by the codec. -The schema will only contain keys from this event. -Therefore, you must have all keys present in all events in order for the automatically generated schema to produce a working schema. -Automatically generated schemas make all fields nullable. -Use the sink's `include_keys` and `exclude_keys` configurations to control what data is included in the auto-generated schema. +Avro fields should use a null [union](https://avro.apache.org/docs/current/specification/#unions) because this will allow missing values. Otherwise, all required fields must be present for each event. Use non-nullable fields only when you are certain they exist. +Use the following options to configure the codec. Option | Required | Type | Description :--- | :--- | :--- | :--- `schema` | Yes | String | The Avro [schema declaration](https://avro.apache.org/docs/current/specification/#schema-declaration). Not required if `auto_schema` is set to true. `auto_schema` | No | Boolean | When set to `true`, automatically generates the Avro [schema declaration](https://avro.apache.org/docs/current/specification/#schema-declaration) from the first event. - -### ndjson codec - -The `ndjson` codec writes each line as a JSON object. +### `ndjson` codec -The `ndjson` codec does not take any configurations. +The `ndjson` codec writes each line as a JSON object. The `ndjson` codec does not take any configurations. +### `json` codec -### json codec - -The `json` codec writes events in a single large JSON file. -Each event is written into an object within a JSON array. +The `json` codec writes events in a single large JSON file. Each event is written into an object within a JSON array. +Use the following options to configure the codec. Option | Required | Type | Description :--- | :--- | :--- | :--- `key_name` | No | String | The name of the key for the JSON array. By default this is `events`. +### `parquet` codec -### parquet codec - -The `parquet` codec writes events into a Parquet file. -When using the Parquet codec, set the `buffer_type` to `in_memory`. +The `parquet` codec writes events into a Parquet file. When using the codec, set `buffer_type` to `in_memory`. -The Parquet codec writes data using the Avro schema. -Because Parquet requires an Avro schema, you may either define the schema yourself, or Data Prepper will automatically generate a schema. -However, we generally recommend that you define your own schema so that it can best meet your needs. +The `parquet` codec writes data using the schema. Because Parquet requires an Avro schema, you may either define the schema yourself or have Data Prepper automatically generate it. Defining your own schema is recommended because this will allow it to be tailored to your particular use case. -For details on the Avro schema and recommendations, see the [Avro codec](#avro-codec) documentation. +For more information about the Avro schema, refer to [Avro codec](#avro-codec). +Use the following options to configure the codec. Option | Required | Type | Description :--- | :--- | :--- | :--- @@ -192,7 +213,7 @@ Option | Required | Type | Description ### Setting a schema with Parquet -The following example shows you how to configure the `s3` sink to write Parquet data into a Parquet file using a schema for [VPC Flow Logs](https://docs.aws.amazon.com/vpc/latest/userguide/flow-logs.html#flow-log-records): +The following example pipeline shows how to configure the `s3` sink to write Parquet data into a Parquet file using a schema for [VPC Flow Logs](https://docs.aws.amazon.com/vpc/latest/userguide/flow-logs.html#flow-log-records): ``` pipeline: @@ -235,4 +256,4 @@ pipeline: event_collect_timeout: PT15M buffer_type: in_memory ``` - +{% include copy-curl.html %} diff --git a/_data-prepper/pipelines/configuration/sources/documentdb.md b/_data-prepper/pipelines/configuration/sources/documentdb.md new file mode 100644 index 0000000000..c453b60a39 --- /dev/null +++ b/_data-prepper/pipelines/configuration/sources/documentdb.md @@ -0,0 +1,97 @@ +--- +layout: default +title: documentdb +parent: Sources +grand_parent: Pipelines +nav_order: 2 +--- + +# documentdb + +The `documentdb` source reads documents from [Amazon DocumentDB](https://aws.amazon.com/documentdb/) collections. +It can read historical data from an export and keep up to date on the data using Amazon DocumentDB [change streams](https://docs.aws.amazon.com/documentdb/latest/developerguide/change_streams.html). + +The `documentdb` source reads data from Amazon DocumentDB and puts that data into an [Amazon Simple Storage Service (Amazon S3)](https://aws.amazon.com/s3/) bucket. +Then, other Data Prepper workers read from the S3 bucket to process data. + +## Usage +The following example pipeline uses the `documentdb` source: + +```yaml +version: "2" +documentdb-pipeline: + source: + documentdb: + host: "docdb-mycluster.cluster-random.us-west-2.docdb.amazonaws.com" + port: 27017 + authentication: + {% raw %}username: ${{aws_secrets:secret:username}} + password: ${{aws_secrets:secret:password}}{% endraw %} + aws: + sts_role_arn: "arn:aws:iam::123456789012:role/MyRole" + s3_bucket: my-bucket + s3_region: us-west-2 + collections: + - collection: my-collection + export: true + stream: true + acknowledgments: true +``` +{% include copy-curl.html %} + +## Configuration + +You can use the following options to configure the `documentdb` source. + +Option | Required | Type | Description +:--- | :--- | :--- | :--- +`host` | Yes | String | The hostname of the Amazon DocumentDB cluster. +`port` | No | Integer | The port number of the Amazon DocumentDB cluster. Defaults to `27017`. +`trust_store_file_path` | No | String | The path to a truststore file that contains the public certificate for the Amazon DocumentDB cluster. +`trust_store_password` | No | String | The password for the truststore specified by `trust_store_file_path`. +`authentication` | Yes | Authentication | The authentication configuration. See the [authentication](#authentication) section for more information. +`collections` | Yes | List | A list of collection configurations. Exactly one collection is required. See the [collections](#collection) section for more information. +`s3_bucket` | Yes | String | The S3 bucket to use for processing events from Amazon DocumentDB. +`s3_prefix` | No | String | An optional Amazon S3 key prefix. By default, there is no key prefix. +`s3_region` | No | String | The AWS Region in which the S3 bucket resides. +`aws` | Yes | AWS | The AWS configuration. See the [aws](#aws) section for more information. +`id_key` | No | String | When specified, the Amazon DocumentDB `_id` field is set to the key name specified by `id_key`. You can use this when you need more information than is provided by the `ObjectId` string saved to your sink. By default, the `_id` is not included as part of the event. +`direct_connection` | No | Boolean | When `true`, the MongoDB driver connects directly to the specified Amazon DocumentDB server(s) without discovering and connecting to the entire replica set. Defaults to `true`. +`read_preference` | No | String | Determines how to read from Amazon DocumentDB. See [Read Preference Modes](https://www.mongodb.com/docs/v3.6/reference/read-preference/#read-preference-modes) for more information. Defaults to `primaryPreferred`. +`disable_s3_read_for_leader` | No | Boolean | When `true`, the current leader node does not read from Amazon S3. It only reads the stream. Defaults to `false`. +`partition_acknowledgment_timeout` | No | Duration | Configures the amount of time during which the node holds a partition. Defaults to `2h`. +`acknowledgments` | No | Boolean | When set to `true`, enables [end-to-end acknowledgments]({{site.url}}{{site.baseurl}}/data-prepper/pipelines/pipelines#end-to-end-acknowledgments) on the source after events are sent to the sinks. +`insecure` | No | Boolean | Disables TLS. Defaults to `false`. Do not use this value in production. +`ssl_insecure_disable_verification` | No | Boolean | Disables TLS hostname verification. Defaults to `false`. Do not enable this flag in production. Instead, use the `trust_store_file_path` to verify the hostname. + +### `authentication` + +The following parameters enable you to configure `authentication` for the Amazon DocumentDB cluster. + +Option | Required | Type | Description +:--- | :--- | :--- | :--- +`username` | Yes | String | The username to use when authenticating with the Amazon DocumentDB cluster. Supports automatic refresh. +`password` | Yes | String | The password to use when authenticating with the Amazon DocumentDB cluster. Supports automatic refresh. + +### `collection` + +The following parameters enable you to configure `collection` to read from the Amazon DocumentDB cluster. + +Option | Required | Type | Description +:--- | :--- | :--- | :--- +`collection` | Yes | String | The name of the collection. +`export` | No | Boolean | Whether to include an export or a full load. Defaults to `true`. +`stream` | No | Boolean | Whether to enable a stream. Defaults to `true`. +`partition_count` | No | Integer | Defines the number of partitions to create in Amazon S3. Defaults to `100`. +`export_batch_size` | No | Integer | Defaults to `10,000`. +`stream_batch_size` | No | Integer | Defaults to `1,000`. + +## `aws` + +The following parameters enable you to configure your access to Amazon DocumentDB. + +Option | Required | Type | Description +:--- | :--- | :--- | :--- +`sts_role_arn` | No | String | The AWS Security Token Service (AWS STS) role to assume for requests to Amazon Simple Queue Service (Amazon SQS) and Amazon S3. Defaults to `null`, which uses the [standard SDK behavior for credentials](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/credentials.html). +`aws_sts_header_overrides` | No | Map | A map of header overrides that the AWS Identity and Access Management (IAM) role assumes for the sink plugin. +`sts_external_id` | No | String | An external STS ID used when Data Prepper assumes the STS role. See `ExternalID` in the [STS AssumeRole](https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html) API reference documentation. diff --git a/_data-prepper/pipelines/configuration/sources/http-source.md b/_data-prepper/pipelines/configuration/sources/http.md similarity index 88% rename from _data-prepper/pipelines/configuration/sources/http-source.md rename to _data-prepper/pipelines/configuration/sources/http.md index b41855cdc2..06933edc1c 100644 --- a/_data-prepper/pipelines/configuration/sources/http-source.md +++ b/_data-prepper/pipelines/configuration/sources/http.md @@ -1,14 +1,16 @@ --- layout: default -title: http_source +title: http parent: Sources grand_parent: Pipelines nav_order: 5 +redirect_from: + - /data-prepper/pipelines/configuration/sources/http-source/ --- -# http_source +# http -`http_source` is a source plugin that supports HTTP. Currently, `http_source` only supports the JSON UTF-8 codec for incoming requests, such as `[{"key1": "value1"}, {"key2": "value2"}]`. The following table describes options you can use to configure the `http_source` source. +The `http` plugin accepts HTTP requests from clients. Currently, `http` only supports the JSON UTF-8 codec for incoming requests, such as `[{"key1": "value1"}, {"key2": "value2"}]`. The following table describes options you can use to configure the `http` source. Option | Required | Type | Description :--- | :--- | :--- | :--- @@ -19,6 +21,7 @@ request_timeout | No | Integer | The request timeout, in milliseconds. Default v thread_count | No | Integer | The number of threads to keep in the ScheduledThreadPool. Default value is `200`. max_connection_count | No | Integer | The maximum allowed number of open connections. Default value is `500`. max_pending_requests | No | Integer | The maximum allowed number of tasks in the `ScheduledThreadPool` work queue. Default value is `1024`. +max_request_length | No | ByteCount | The maximum number of bytes allowed in the payload of a single HTTP request. Default value is `10mb`. authentication | No | Object | An authentication configuration. By default, this creates an unauthenticated server for the pipeline. This uses pluggable authentication for HTTPS. To use basic authentication define the `http_basic` plugin with a `username` and `password`. To provide customer authentication, use or create a plugin that implements [ArmeriaHttpAuthenticationProvider](https://github.com/opensearch-project/data-prepper/blob/1.2.0/data-prepper-plugins/armeria-common/src/main/java/com/amazon/dataprepper/armeria/authentication/ArmeriaHttpAuthenticationProvider.java). ssl | No | Boolean | Enables TLS/SSL. Default value is false. ssl_certificate_file | Conditionally | String | SSL certificate chain file path or Amazon Simple Storage Service (Amazon S3) path. Amazon S3 path example `s3:///`. Required if `ssl` is set to true and `use_acm_certificate_for_ssl` is set to false. @@ -35,7 +38,7 @@ Content will be added to this section.---> ## Metrics -The `http_source` source includes the following metrics. +The `http` source includes the following metrics. ### Counters diff --git a/_data-prepper/pipelines/configuration/sources/otel-logs-source.md b/_data-prepper/pipelines/configuration/sources/otel-logs-source.md index 58d8a2b059..068369efaf 100644 --- a/_data-prepper/pipelines/configuration/sources/otel-logs-source.md +++ b/_data-prepper/pipelines/configuration/sources/otel-logs-source.md @@ -21,7 +21,8 @@ You can configure the `otel_logs_source` source with the following options. | Option | Type | Description | | :--- | :--- | :--- | | port | int | Represents the port that the `otel_logs_source` source is running on. Default value is `21892`. | -| path | string | Represents the path for sending unframed HTTP requests. You can use this option to support an unframed gRPC request with an HTTP idiomatic path to a configurable path. The path should start with `/`, and its length should be at least 1. The `/opentelemetry.proto.collector.logs.v1.LogsService/Export` endpoint is disabled for both gRPC and HTTP requests if the path is configured. The path can contain a `${pipelineName}` placeholder, which is replaced with the pipeline name. If the value is empty and `unframed_requests` is `true`, then the path that the source provides is `/opentelemetry.proto.collector.logs.v1.LogsService/Export`. | +| path | string | Represents the path for sending unframed HTTP requests. You can use this option to support an unframed gRPC request with an HTTP idiomatic path to a configurable path. The path should start with `/`, and its length should be at least 1. The `/opentelemetry.proto.collector.logs.v1.LogsService/Export` endpoint is disabled for both gRPC and HTTP requests if the path is configured. The path can contain a `${pipelineName}` placeholder, which is replaced with the pipeline name. If the value is empty and `unframed_requests` is `true`, then the source provides the path `/opentelemetry.proto.collector.logs.v1.LogsService/Export`. | +| max_request_length | No | ByteCount | The maximum number of bytes allowed in the payload of a single gRPC or HTTP request. Default value is `10mb`. | request_timeout | int | Represents the request timeout duration in milliseconds. Default value is `10000`. | | health_check_service | Boolean | Enables the gRPC health check service under `grpc.health.v1/Health/Check`. Default value is `false`. | | proto_reflection_service | Boolean | Enables a reflection service for Protobuf services (see [ProtoReflectionService](https://grpc.github.io/grpc-java/javadoc/io/grpc/protobuf/services/ProtoReflectionService.html) and [gRPC reflection](https://github.com/grpc/grpc-java/blob/master/documentation/server-reflection-tutorial.md)). Default value is `false`. | diff --git a/_data-prepper/pipelines/configuration/sources/otel-metrics-source.md b/_data-prepper/pipelines/configuration/sources/otel-metrics-source.md index 0301963538..bea74a96d3 100644 --- a/_data-prepper/pipelines/configuration/sources/otel-metrics-source.md +++ b/_data-prepper/pipelines/configuration/sources/otel-metrics-source.md @@ -19,6 +19,7 @@ proto_reflection_service | No | Boolean | Enables a reflection service for Proto unframed_requests | No | Boolean | Enables requests not framed using the gRPC wire protocol. thread_count | No | Integer | The number of threads to keep in the `ScheduledThreadPool`. Default value is `200`. max_connection_count | No | Integer | The maximum allowed number of open connections. Default value is `500`. +max_request_length | No | ByteCount | The maximum number of bytes allowed in the payload of a single gRPC or HTTP request. Default value is `10mb`. ssl | No | Boolean | Enables connections to the OpenTelemetry source port over TLS/SSL. Default value is `true`. sslKeyCertChainFile | Conditionally | String | File-system path or Amazon Simple Storage Service (Amazon S3) path to the security certificate (for example, `"config/demo-data-prepper.crt"` or `"s3://my-secrets-bucket/demo-data-prepper.crt"`). Required if `ssl` is set to `true`. sslKeyFile | Conditionally | String | File-system path or Amazon S3 path to the security key (for example, `"config/demo-data-prepper.key"` or `"s3://my-secrets-bucket/demo-data-prepper.key"`). Required if `ssl` is set to `true`. diff --git a/_data-prepper/pipelines/configuration/sources/otel-trace-source.md b/_data-prepper/pipelines/configuration/sources/otel-trace-source.md index 137592bbe8..1be7864c33 100644 --- a/_data-prepper/pipelines/configuration/sources/otel-trace-source.md +++ b/_data-prepper/pipelines/configuration/sources/otel-trace-source.md @@ -24,6 +24,7 @@ proto_reflection_service | No | Boolean | Enables a reflection service for Proto unframed_requests | No | Boolean | Enable requests not framed using the gRPC wire protocol. thread_count | No | Integer | The number of threads to keep in the ScheduledThreadPool. Default value is `200`. max_connection_count | No | Integer | The maximum allowed number of open connections. Default value is `500`. +max_request_length | No | ByteCount | The maximum number of bytes allowed in the payload of a single gRPC or HTTP request. Default value is `10mb`. ssl | No | Boolean | Enables connections to the OTel source port over TLS/SSL. Defaults to `true`. sslKeyCertChainFile | Conditionally | String | File system path or Amazon Simple Storage Service (Amazon S3) path to the security certificate (for example, `"config/demo-data-prepper.crt"` or `"s3://my-secrets-bucket/demo-data-prepper.crt"`). Required if `ssl` is set to `true`. sslKeyFile | Conditionally | String | File system path or Amazon S3 path to the security key (for example, `"config/demo-data-prepper.key"` or `"s3://my-secrets-bucket/demo-data-prepper.key"`). Required if `ssl` is set to `true`. diff --git a/_data-prepper/pipelines/configuration/sources/s3.md b/_data-prepper/pipelines/configuration/sources/s3.md index 7a3746bab6..5a7d9986e5 100644 --- a/_data-prepper/pipelines/configuration/sources/s3.md +++ b/_data-prepper/pipelines/configuration/sources/s3.md @@ -104,7 +104,7 @@ Option | Required | Type | Description `s3_select` | No | [s3_select](#s3_select) | The Amazon S3 Select configuration. `scan` | No | [scan](#scan) | The S3 scan configuration. `delete_s3_objects_on_read` | No | Boolean | When `true`, the S3 scan attempts to delete S3 objects after all events from the S3 object are successfully acknowledged by all sinks. `acknowledgments` should be enabled when deleting S3 objects. Default is `false`. -`workers` | No | Integer | Configures the number of worker threads that the source uses to read data from S3. Leaving this value at the default unless your S3 objects are less than 1MB. Performance may decrease for larger S3 objects. This setting only affects SQS-based sources. Default is `1`. +`workers` | No | Integer | Configures the number of worker threads that the source uses to read data from S3. Leave this value as the default unless your S3 objects are less than 1 MB in size. Performance may decrease for larger S3 objects. This setting affects SQS-based sources and S3-Scan sources. Default is `1`. diff --git a/_data-prepper/pipelines/expression-syntax.md b/_data-prepper/pipelines/expression-syntax.md index be0be6f792..b4603e34f9 100644 --- a/_data-prepper/pipelines/expression-syntax.md +++ b/_data-prepper/pipelines/expression-syntax.md @@ -114,7 +114,23 @@ null != null != /response ``` -#### Conditional expression +## Type check operator + +The type check operator tests whether a JSON Pointer is of a certain data type. + +### Syntax +``` + typeof +``` +Supported data types are `integer`, `long`, `boolean`, `double`, `string`, `map`, and `array`. + +#### Example +``` +/response typeof integer +/message typeof string +``` + +### Conditional expression A conditional expression is used to chain together multiple expressions and/or values. @@ -218,6 +234,7 @@ White space is **required** surrounding set initializers, priority expressions, | `==`, `!=` | Equality operators | No | `/status == 200`
`/status_code==200` | | | `and`, `or`, `not` | Conditional operators | Yes | `/a<300 and /b>200` | `/b<300and/b>200` | | `,` | Set value delimiter | No | `/a in {200, 202}`
`/a in {200,202}`
`/a in {200 , 202}` | `/a in {200,}` | +| `typeof` | Type check operator | Yes | `/a typeof integer`
`/a typeof long`
`/a typeof string`
`/a typeof double`
`/a typeof boolean`
`/a typeof map`
`/a typeof array` |`/a typeof /b`
`/a typeof 2` | ## Functions diff --git a/_data/versions.json b/_data/versions.json index 969f93681b..0c99ed871e 100644 --- a/_data/versions.json +++ b/_data/versions.json @@ -1,10 +1,11 @@ { - "current": "2.14", + "current": "2.15", "all": [ - "2.14", + "2.15", "1.3" ], "archived": [ + "2.14", "2.13", "2.12", "2.11", @@ -23,7 +24,7 @@ "1.1", "1.0" ], - "latest": "2.14" + "latest": "2.15" } diff --git a/_field-types/supported-field-types/constant-keyword.md b/_field-types/supported-field-types/constant-keyword.md new file mode 100644 index 0000000000..bf1e4afc70 --- /dev/null +++ b/_field-types/supported-field-types/constant-keyword.md @@ -0,0 +1,42 @@ +--- +layout: default +title: Constant keyword +nav_order: 71 +has_children: false +parent: String field types +grand_parent: Supported field types +--- + +# Constant keyword field type + +A constant keyword field uses the same value for all documents in the index. + +When a search request spans multiple indexes, you can filter on a constant keyword field to match documents from indexes with the given constant value but not from indexes with a different value. + +## Example + +The following query creates a mapping with a constant keyword field: + +```json +PUT romcom_movies +{ + "mappings" : { + "properties" : { + "genre" : { + "type": "constant_keyword", + "value" : "Romantic comedy" + } + } + } +} +``` +{% include copy-curl.html %} + +## Parameters + +The following table lists the parameters accepted by constant keyword field types. All values are required. + +Parameter | Description +:--- | :--- +`value` | The string field value for all documents in the index. + diff --git a/_field-types/supported-field-types/derived.md b/_field-types/supported-field-types/derived.md new file mode 100644 index 0000000000..2ca00927d1 --- /dev/null +++ b/_field-types/supported-field-types/derived.md @@ -0,0 +1,903 @@ +--- +layout: default +title: Derived +nav_order: 62 +has_children: false +parent: Supported field types +--- + +# Derived field type +**Introduced 2.15** +{: .label .label-purple } + +Derived fields allow you to create new fields dynamically by executing scripts on existing fields. The existing fields can be either retrieved from the `_source` field, which contains the original document, or from a field's doc values. Once you define a derived field either in an index mapping or within a search request, you can use the field in a query in the same way you would use a regular field. + +## When to use derived fields + +Derived fields offer flexibility in field manipulation and prioritize storage efficiency. However, +because they are computed at query time, they can reduce query performance. Derived fields are particularly useful in scenarios requiring real-time data transformation, such as: + +- **Log analysis**: Extracting timestamps and log levels from log messages. +- **Performance metrics**: Calculating response times from start and end timestamps. +- **Security analytics**: Real-time IP geolocation and user-agent parsing for threat detection. +- **Experimental use cases**: Testing new data transformations, creating temporary fields for A/B testing, or generating one-time reports without altering mappings or reindexing data. + +Despite the potential performance impact of query-time computations, the flexibility and storage efficiency of derived fields make them a valuable tool for these applications. + +## Current limitations + +Currently, derived fields have the following limitations: + +- **Aggregation, scoring, and sorting**: Not yet supported. +- **Dashboard support**: These fields are not displayed in the list of available fields in OpenSearch Dashboards. However, you can still use them for filtering if you know the derived field name. +- **Chained derived fields**: One derived field cannot be used to define another derived field. +- **Join field type**: Derived fields are not supported for the [join field type]({{site.url}}{{site.baseurl}}/opensearch/supported-field-types/join/). +- **Concurrent segment search**: Derived fields are not supported for [concurrent segment search]({{site.url}}{{site.baseurl}}/search-plugins/concurrent-segment-search/). + +We are planning to address these limitations in future versions. + +## Prerequisites + +Before using a derived field, be sure to satisfy the following prerequisites: + +- **Enable `_source` or `doc_values`**: Ensure that either the `_source` field or doc values is enabled for the fields used in your script. +- **Enable expensive queries**: Ensure that [`search.allow_expensive_queries`]({{site.url}}{{site.baseurl}}/query-dsl/index/#expensive-queries) is set to `true`. +- **Feature control**: Derived fields are enabled by default. You can enable or disable derived fields by using the following settings: + - **Index level**: Update the `index.query.derived_field.enabled` setting. + - **Cluster level**: Update the `search.derived_field.enabled` setting. + Both settings are dynamic, so they can be changed without reindexing or node restarts. +- **Performance considerations**: Before using derived fields, evaluate the [performance implications](#performance) to ensure that derived fields meet your scale requirements. + +## Defining derived fields + +You can define derived fields [in index mappings](#defining-derived-fields-in-index-mappings) or [directly within a search request](#defining-and-searching-derived-fields-in-a-search-request). + +## Example setup + +To try the examples on this page, first create the following `logs` index: + +```json +PUT logs +{ + "mappings": { + "properties": { + "request": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword" + } + } + }, + "client_ip": { + "type": "keyword" + } + } + } +} +``` +{% include copy-curl.html %} + +Add sample documents to the index: + +```json +POST _bulk +{ "index" : { "_index" : "logs", "_id" : "1" } } +{ "request": "894030400 GET /english/images/france98_venues.gif HTTP/1.0 200 778", "clientip": "61.177.2.0" } +{ "index" : { "_index" : "logs", "_id" : "2" } } +{ "request": "894140400 GET /french/playing/mascot/mascot.html HTTP/1.1 200 5474", "clientip": "185.92.2.0" } +{ "index" : { "_index" : "logs", "_id" : "3" } } +{ "request": "894250400 POST /english/venues/images/venue_header.gif HTTP/1.0 200 711", "clientip": "61.177.2.0" } +{ "index" : { "_index" : "logs", "_id" : "4" } } +{ "request": "894360400 POST /images/home_fr_button.gif HTTP/1.1 200 2140", "clientip": "129.178.2.0" } +{ "index" : { "_index" : "logs", "_id" : "5" } } +{ "request": "894470400 DELETE /images/102384s.gif HTTP/1.0 200 785", "clientip": "227.177.2.0" } +``` +{% include copy-curl.html %} + +## Defining derived fields in index mappings + +To derive the `timestamp`, `method`, and `size` fields from the `request` field indexed in the `logs` index, configure the following mappings: + +```json +PUT /logs/_mapping +{ + "derived": { + "timestamp": { + "type": "date", + "format": "MM/dd/yyyy", + "script": { + "source": """ + emit(Long.parseLong(doc["request.keyword"].value.splitOnToken(" ")[0])) + """ + } + }, + "method": { + "type": "keyword", + "script": { + "source": """ + emit(doc["request.keyword"].value.splitOnToken(" ")[1]) + """ + } + }, + "size": { + "type": "long", + "script": { + "source": """ + emit(Long.parseLong(doc["request.keyword"].value.splitOnToken(" ")[5])) + """ + } + } + } +} +``` +{% include copy-curl.html %} + +Note that the `timestamp` field has an additional `format` parameter that specifies the format in which to display `date` fields. If you don't include a `format` parameter, then the format defaults to `strict_date_time_no_millis`. For more information about supported date formats, see [Parameters](#parameters). + +## Parameters + +The following table lists the parameters accepted by `derived` field types. All parameters are dynamic and can be modified without reindexing documents. + +| Parameter | Required/Optional | Description | +| :--- | :--- | :--- | +| `type` | Required | The type of the derived field. Supported types are `boolean`, `date`, `geo_point`, `ip`, `keyword`, `text`, `long`, `double`, `float`, and `object`. | +| `script` | Required | The script associated with the derived field. Any value emitted from the script must be emitted using `emit()`. The type of the emitted value must match the `type` of the derived field. Scripts have access to both the `doc_values` and `_source` fields if those are enabled. The doc value of a field can be accessed using `doc['field_name'].value`, and the source can be accessed using `params._source["field_name"]`. | +| `format` | Optional | The format used for parsing dates. Only applicable to `date` fields. Valid values are `strict_date_time_no_millis`, `strict_date_optional_time`, and `epoch_millis`. For more information, see [Formats]({{site.url}}{{site.baseurl}}/field-types/supported-field-types/date/#formats).| +| `ignore_malformed`| Optional | A Boolean value that specifies whether to ignore malformed values when running a query on a derived field. Default value is `false` (throw an exception when encountering malformed values). | +| `prefilter_field` | Optional | An indexed text field provided to boost the performance of derived fields. Specifies an existing indexed field on which to filter prior to filtering on the derived field. For more information, see [Prefilter field](#prefilter-field). | + +## Emitting values in scripts + +The `emit()` function is available only within the derived field script context. It is used to emit one or multiple (for a multi-valued field) script values for a document on which the script runs. + +The following table lists the `emit()` function formats for the supported field types. + +| Type | Emit format | Multi-valued fields supported| +|-----------|----------------------------------|--------------| +| `boolean` | `emit(boolean)` | No | +| `double` | `emit(double)` | Yes | +| `date` | `emit(long timeInMilis)` | Yes | +| `float` | `emit(float)` | Yes | +| `geo_point`| `emit(double lat, double lon)` | Yes | +| `ip` | `emit(String ip)` | Yes | +| `keyword` | `emit(String)` | Yes | +| `long` | `emit(long)` | Yes | +| `object` | `emit(String json)` (valid JSON) | Yes | +| `text` | `emit(String)` | Yes | + +By default, a type mismatch between a derived field and its emitted value will result in the search request failing with an error. If `ignore_malformed` is set to `true`, then the failing document is skipped and the search request succeeds. +{: .note} + +The size limit of the emitted values is 1 MB per document. +{: .important} + +## Searching derived fields defined in index mappings + +To search derived fields, use the same syntax as when searching regular fields. For example, the following request searches for documents with derived `timestamp` field in the specified range: + +```json +POST /logs/_search +{ + "query": { + "range": { + "timestamp": { + "gte": "1970-01-11T08:20:30.400Z", + "lte": "1970-01-11T08:26:00.400Z" + } + } + }, + "fields": ["timestamp"] +} +``` +{% include copy-curl.html %} + +The response contains the matching documents: + +
+ + Response + + {: .text-delta} + +```json +{ + "took": 315, + "timed_out": false, + "_shards": { + "total": 1, + "successful": 1, + "skipped": 0, + "failed": 0 + }, + "hits": { + "total": { + "value": 4, + "relation": "eq" + }, + "max_score": 1, + "hits": [ + { + "_index": "logs", + "_id": "1", + "_score": 1, + "_source": { + "request": "894030400 GET /english/images/france98_venues.gif HTTP/1.0 200 778", + "clientip": "61.177.2.0" + }, + "fields": { + "timestamp": [ + "1970-01-11T08:20:30.400Z" + ] + } + }, + { + "_index": "logs", + "_id": "2", + "_score": 1, + "_source": { + "request": "894140400 GET /french/playing/mascot/mascot.html HTTP/1.1 200 5474", + "clientip": "185.92.2.0" + }, + "fields": { + "timestamp": [ + "1970-01-11T08:22:20.400Z" + ] + } + }, + { + "_index": "logs", + "_id": "3", + "_score": 1, + "_source": { + "request": "894250400 POST /english/venues/images/venue_header.gif HTTP/1.0 200 711", + "clientip": "61.177.2.0" + }, + "fields": { + "timestamp": [ + "1970-01-11T08:24:10.400Z" + ] + } + }, + { + "_index": "logs", + "_id": "4", + "_score": 1, + "_source": { + "request": "894360400 POST /images/home_fr_button.gif HTTP/1.1 200 2140", + "clientip": "129.178.2.0" + }, + "fields": { + "timestamp": [ + "1970-01-11T08:26:00.400Z" + ] + } + } + ] + } +} +``` +
+ +## Defining and searching derived fields in a search request + +You can also define derived fields directly in a search request and query them along with regular indexed fields. For example, the following request creates the `url` and `status` derived fields and searches those fields along with the regular `request` and `clientip` fields: + +```json +POST /logs/_search +{ + "derived": { + "url": { + "type": "text", + "script": { + "source": """ + emit(doc["request"].value.splitOnToken(" ")[2]) + """ + } + }, + "status": { + "type": "keyword", + "script": { + "source": """ + emit(doc["request"].value.splitOnToken(" ")[4]) + """ + } + } + }, + "query": { + "bool": { + "must": [ + { + "term": { + "clientip": "61.177.2.0" + } + }, + { + "match": { + "url": "images" + } + }, + { + "term": { + "status": "200" + } + } + ] + } + }, + "fields": ["request", "clientip", "url", "status"] +} +``` +{% include copy-curl.html %} + +The response contains the matching documents: + +
+ + Response + + {: .text-delta} + +```json +{ + "took": 6, + "timed_out": false, + "_shards": { + "total": 1, + "successful": 1, + "skipped": 0, + "failed": 0 + }, + "hits": { + "total": { + "value": 2, + "relation": "eq" + }, + "max_score": 2.8754687, + "hits": [ + { + "_index": "logs", + "_id": "1", + "_score": 2.8754687, + "_source": { + "request": "894030400 GET /english/images/france98_venues.gif HTTP/1.0 200 778", + "clientip": "61.177.2.0" + }, + "fields": { + "request": [ + "894030400 GET /english/images/france98_venues.gif HTTP/1.0 200 778" + ], + "clientip": [ + "61.177.2.0" + ], + "url": [ + "/english/images/france98_venues.gif" + ], + "status": [ + "200" + ] + } + }, + { + "_index": "logs", + "_id": "3", + "_score": 2.8754687, + "_source": { + "request": "894250400 POST /english/venues/images/venue_header.gif HTTP/1.0 200 711", + "clientip": "61.177.2.0" + }, + "fields": { + "request": [ + "894250400 POST /english/venues/images/venue_header.gif HTTP/1.0 200 711" + ], + "clientip": [ + "61.177.2.0" + ], + "url": [ + "/english/venues/images/venue_header.gif" + ], + "status": [ + "200" + ] + } + } + ] + } +} +``` +
+ +Derived fields use the default analyzer specified in the index analysis settings during search. You can override the default analyzer or specify a search analyzer within a search request in the same way as with regular fields. For more information, see [Analyzers]({{site.url}}{{site.baseurl}}/analyzers/). +{: .note} + +When both an index mapping and a search definition are present for a field, the search definition takes precedence. +{: .note} + +### Retrieving fields + +You can retrieve derived fields using the `fields` parameter in the search request in the same way as with regular fields, as shown in the preceding examples. You can also use wildcards to retrieve all derived fields that match a given pattern. + +### Highlighting + +Derived fields of type `text` support highlighting using the [unified highlighter]({{site.url}}{{site.baseurl}}/opensearch/search/highlight#the-unified-highlighter). For example, the following request specifies to highlight the derived `url` field: + +```json +POST /logs/_search +{ + "derived": { + "url": { + "type": "text", + "script": { + "source": """ + emit(doc["request"].value.splitOnToken(" " )[2]) + """ + } + } + }, + "query": { + "bool": { + "must": [ + { + "term": { + "clientip": "61.177.2.0" + } + }, + { + "match": { + "url": "images" + } + } + ] + } + }, + "fields": ["request", "clientip", "url"], + "highlight": { + "fields": { + "url": {} + } + } +} +``` +{% include copy-curl.html %} + +The response specifies highlighting in the `url` field: + +
+ + Response + + {: .text-delta} + +```json +{ + "took": 45, + "timed_out": false, + "_shards": { + "total": 1, + "successful": 1, + "skipped": 0, + "failed": 0 + }, + "hits": { + "total": { + "value": 2, + "relation": "eq" + }, + "max_score": 1.8754687, + "hits": [ + { + "_index": "logs", + "_id": "1", + "_score": 1.8754687, + "_source": { + "request": "894030400 GET /english/images/france98_venues.gif HTTP/1.0 200 778", + "clientip": "61.177.2.0" + }, + "fields": { + "request": [ + "894030400 GET /english/images/france98_venues.gif HTTP/1.0 200 778" + ], + "clientip": [ + "61.177.2.0" + ], + "url": [ + "/english/images/france98_venues.gif" + ] + }, + "highlight": { + "url": [ + "/english/images/france98_venues.gif" + ] + } + }, + { + "_index": "logs", + "_id": "3", + "_score": 1.8754687, + "_source": { + "request": "894250400 POST /english/venues/images/venue_header.gif HTTP/1.0 200 711", + "clientip": "61.177.2.0" + }, + "fields": { + "request": [ + "894250400 POST /english/venues/images/venue_header.gif HTTP/1.0 200 711" + ], + "clientip": [ + "61.177.2.0" + ], + "url": [ + "/english/venues/images/venue_header.gif" + ] + }, + "highlight": { + "url": [ + "/english/venues/images/venue_header.gif" + ] + } + } + ] + } +} +``` +
+ +## Performance + +Derived fields are not indexed but are computed dynamically by retrieving values from the `_source` field or doc values. Thus, they run more slowly. To improve performance, try the following: + +- Prune the search space by adding query filters on indexed fields in conjunction with derived fields. +- Use doc values instead of `_source` in the script for faster access, whenever applicable. +- Consider using a [`prefilter_field`](#prefilter-field) to automatically prune the search space without explicit filters in the search request. + +### Prefilter field + +Specifying a prefilter field helps to prune the search space without adding explicit filters in the search request. The prefilter field specifies an existing indexed field (`prefilter_field`) on which to filter automatically when constructing the query. The `prefilter_field` must be a text field (either [`text`]({{site.url}}{{site.baseurl}}/field-types/supported-field-types/text/) or [`match_only_text`]({{site.url}}{{site.baseurl}}/field-types/supported-field-types/match-only-text/)). + +For example, you can add a `prefilter_field` to the `method` derived field. Update the index mapping, specifying to prefilter on the `request` field: + +```json +PUT /logs/_mapping +{ + "derived": { + "method": { + "type": "keyword", + "script": { + "source": """ + emit(doc["request.keyword"].value.splitOnToken(" ")[1]) + """ + }, + "prefilter_field": "request" + } + } +} +``` +{% include copy-curl.html %} + +Now search using a query on the `method` derived field: + +```json +POST /logs/_search +{ + "profile": true, + "query": { + "term": { + "method": { + "value": "GET" + } + } + }, + "fields": ["method"] +} +``` +{% include copy-curl.html %} + +OpenSearch automatically adds a filter on the `request` field to your query: + +```json +"#request:GET #DerivedFieldQuery (Query: [ method:GET])" +``` + +You can use the `profile` option to analyze derived field performance, as shown in the preceding example. +{: .tip} + +## Derived object fields + +A script can emit a valid JSON object so that you can query subfields without indexing them, in the same way as with regular fields. This is useful for large JSON objects that require occasional searches on some subfields. In this case, indexing the subfields is expensive, while defining derived fields for each subfield also adds a lot of resource overhead. If you don't [explicitly provide the subfield type](#explicit-subfield-type), then the subfield type is [inferred](#inferred-subfield-type). + +For example, the following request defines a `derived_request_object` derived field as an `object` type: + +```json +PUT logs_object +{ + "mappings": { + "properties": { + "request_object": { "type": "text" } + }, + "derived": { + "derived_request_object": { + "type": "object", + "script": { + "source": "emit(params._source[\"request_object\"])" + } + } + } + } +} +``` +{% include copy-curl.html %} + +Consider the following documents, in which the `request_object` is a string representation of a JSON object: + +```json +POST _bulk +{ "index" : { "_index" : "logs_object", "_id" : "1" } } +{ "request_object": "{\"@timestamp\": 894030400, \"clientip\":\"61.177.2.0\", \"request\": \"GET /english/venues/images/venue_header.gif HTTP/1.0\", \"status\": 200, \"size\": 711}" } +{ "index" : { "_index" : "logs_object", "_id" : "2" } } +{ "request_object": "{\"@timestamp\": 894140400, \"clientip\":\"129.178.2.0\", \"request\": \"GET /images/home_fr_button.gif HTTP/1.1\", \"status\": 200, \"size\": 2140}" } +{ "index" : { "_index" : "logs_object", "_id" : "3" } } +{ "request_object": "{\"@timestamp\": 894240400, \"clientip\":\"227.177.2.0\", \"request\": \"GET /images/102384s.gif HTTP/1.0\", \"status\": 400, \"size\": 785}" } +{ "index" : { "_index" : "logs_object", "_id" : "4" } } +{ "request_object": "{\"@timestamp\": 894340400, \"clientip\":\"61.177.2.0\", \"request\": \"GET /english/images/venue_bu_city_on.gif HTTP/1.0\", \"status\": 400, \"size\": 1397}\n" } +{ "index" : { "_index" : "logs_object", "_id" : "5" } } +{ "request_object": "{\"@timestamp\": 894440400, \"clientip\":\"132.176.2.0\", \"request\": \"GET /french/news/11354.htm HTTP/1.0\", \"status\": 200, \"size\": 3460, \"is_active\": true}" } +``` +{% include copy-curl.html %} + +The following query searches the `@timestamp` subfield of the `derived_request_object`: + +```json +POST /logs_object/_search +{ + "query": { + "range": { + "derived_request_object.@timestamp": { + "gte": "894030400", + "lte": "894140400" + } + } + }, + "fields": ["derived_request_object.@timestamp"] +} +``` +{% include copy-curl.html %} + +The response contains the matching documents: + +
+ + Response + + {: .text-delta} + +```json +{ + "took": 26, + "timed_out": false, + "_shards": { + "total": 1, + "successful": 1, + "skipped": 0, + "failed": 0 + }, + "hits": { + "total": { + "value": 2, + "relation": "eq" + }, + "max_score": 1, + "hits": [ + { + "_index": "logs_object", + "_id": "1", + "_score": 1, + "_source": { + "request_object": """{"@timestamp": 894030400, "clientip":"61.177.2.0", "request": "GET /english/venues/images/venue_header.gif HTTP/1.0", "status": 200, "size": 711}""" + }, + "fields": { + "derived_request_object.@timestamp": [ + 894030400 + ] + } + }, + { + "_index": "logs_object", + "_id": "2", + "_score": 1, + "_source": { + "request_object": """{"@timestamp": 894140400, "clientip":"129.178.2.0", "request": "GET /images/home_fr_button.gif HTTP/1.1", "status": 200, "size": 2140}""" + }, + "fields": { + "derived_request_object.@timestamp": [ + 894140400 + ] + } + } + ] + } +} +``` + +
+ +You can also specify to highlight a derived object field: + +```json +POST /logs_object/_search +{ + "query": { + "bool": { + "must": [ + { + "term": { + "derived_request_object.clientip": "61.177.2.0" + } + }, + { + "match": { + "derived_request_object.request": "images" + } + } + ] + } + }, + "fields": ["derived_request_object.*"], + "highlight": { + "fields": { + "derived_request_object.request": {} + } + } +} +``` +{% include copy-curl.html %} + +The response adds highlighting to the `derived_request_object.request` field: + +
+ + Response + + {: .text-delta} + +```json +{ + "took": 5, + "timed_out": false, + "_shards": { + "total": 1, + "successful": 1, + "skipped": 0, + "failed": 0 + }, + "hits": { + "total": { + "value": 2, + "relation": "eq" + }, + "max_score": 2, + "hits": [ + { + "_index": "logs_object", + "_id": "1", + "_score": 2, + "_source": { + "request_object": """{"@timestamp": 894030400, "clientip":"61.177.2.0", "request": "GET /english/venues/images/venue_header.gif HTTP/1.0", "status": 200, "size": 711}""" + }, + "fields": { + "derived_request_object.request": [ + "GET /english/venues/images/venue_header.gif HTTP/1.0" + ], + "derived_request_object.clientip": [ + "61.177.2.0" + ] + }, + "highlight": { + "derived_request_object.request": [ + "GET /english/venues/images/venue_header.gif HTTP/1.0" + ] + } + }, + { + "_index": "logs_object", + "_id": "4", + "_score": 2, + "_source": { + "request_object": """{"@timestamp": 894340400, "clientip":"61.177.2.0", "request": "GET /english/images/venue_bu_city_on.gif HTTP/1.0", "status": 400, "size": 1397} +""" + }, + "fields": { + "derived_request_object.request": [ + "GET /english/images/venue_bu_city_on.gif HTTP/1.0" + ], + "derived_request_object.clientip": [ + "61.177.2.0" + ] + }, + "highlight": { + "derived_request_object.request": [ + "GET /english/images/venue_bu_city_on.gif HTTP/1.0" + ] + } + } + ] + } +} +``` + +
+ +### Inferred subfield type + +Type inference is based on the same logic as [Dynamic mapping]({{site.url}}{{site.baseurl}}/opensearch/mappings#dynamic-mapping). Instead of inferring the subfield type from the first document, a random sample of documents is used to infer the type. If the subfield isn't found in any documents from the random sample, type inference fails and logs a warning. For subfields that seldom occur in documents, consider defining the explicit field type. Using dynamic type inference for such subfields may result in a query returning no results, like for a missing field. + +### Explicit subfield type + +To define the explicit subfield type, provide the `type` parameter in the `properties` object. In the following example, the `derived_logs_object.is_active` field is defined as `boolean`. Because this field is only present in one of the documents, its type inference might fail, so it's important to define the explicit type: + +```json +POST /logs_object/_search +{ + "derived": { + "derived_request_object": { + "type": "object", + "script": { + "source": "emit(params._source[\"request_object\"])" + }, + "properties": { + "is_active": "boolean" + } + } + }, + "query": { + "term": { + "derived_request_object.is_active": true + } + }, + "fields": ["derived_request_object.is_active"] +} +``` +{% include copy-curl.html %} + +The response contains the matching documents: + +
+ + Response + + {: .text-delta} + +```json +{ + "took": 13, + "timed_out": false, + "_shards": { + "total": 1, + "successful": 1, + "skipped": 0, + "failed": 0 + }, + "hits": { + "total": { + "value": 1, + "relation": "eq" + }, + "max_score": 1, + "hits": [ + { + "_index": "logs_object", + "_id": "5", + "_score": 1, + "_source": { + "request_object": """{"@timestamp": 894440400, "clientip":"132.176.2.0", "request": "GET /french/news/11354.htm HTTP/1.0", "status": 200, "size": 3460, "is_active": true}""" + }, + "fields": { + "derived_request_object.is_active": [ + true + ] + } + } + ] + } +} +``` + +
diff --git a/_field-types/supported-field-types/index.md b/_field-types/supported-field-types/index.md index 69ca0032be..dbff7c30f2 100644 --- a/_field-types/supported-field-types/index.md +++ b/_field-types/supported-field-types/index.md @@ -23,12 +23,13 @@ Boolean | [`boolean`]({{site.url}}{{site.baseurl}}/field-types/supported-field-t IP | [`ip`]({{site.url}}{{site.baseurl}}/field-types/supported-field-types/ip/): An IP address in IPv4 or IPv6 format. [Range]({{site.url}}{{site.baseurl}}/field-types/supported-field-types/range/) | A range of values (`integer_range`, `long_range`, `double_range`, `float_range`, `date_range`, `ip_range`). [Object]({{site.url}}{{site.baseurl}}/field-types/supported-field-types/object-fields/)| [`object`]({{site.url}}{{site.baseurl}}/field-types/supported-field-types/object/): A JSON object.
[`nested`]({{site.url}}{{site.baseurl}}/field-types/supported-field-types/nested/): Used when objects in an array need to be indexed independently as separate documents.
[`flat_object`]({{site.url}}{{site.baseurl}}/field-types/supported-field-types/flat-object/): A JSON object treated as a string.
[`join`]({{site.url}}{{site.baseurl}}/field-types/supported-field-types/join/): Establishes a parent-child relationship between documents in the same index. -[String]({{site.url}}{{site.baseurl}}/field-types/supported-field-types/string/)|[`keyword`]({{site.url}}{{site.baseurl}}/field-types/supported-field-types/keyword/): Contains a string that is not analyzed.
[`text`]({{site.url}}{{site.baseurl}}/field-types/supported-field-types/text/): Contains a string that is analyzed.
[`match_only_text`]({{site.url}}{{site.baseurl}}/field-types/supported-field-types/match-only-text/): A space-optimized version of a `text` field.
[`token_count`]({{site.url}}{{site.baseurl}}/field-types/supported-field-types/token-count/): Stores the number of analyzed tokens in a string. +[String]({{site.url}}{{site.baseurl}}/field-types/supported-field-types/string/)|[`keyword`]({{site.url}}{{site.baseurl}}/field-types/supported-field-types/keyword/): Contains a string that is not analyzed.
[`text`]({{site.url}}{{site.baseurl}}/field-types/supported-field-types/text/): Contains a string that is analyzed.
[`match_only_text`]({{site.url}}{{site.baseurl}}/field-types/supported-field-types/match-only-text/): A space-optimized version of a `text` field.
[`token_count`]({{site.url}}{{site.baseurl}}/field-types/supported-field-types/token-count/): Stores the number of analyzed tokens in a string.
[`wildcard`]({{site.url}}{{site.baseurl}}/field-types/supported-field-types/token-count/): A variation of `keyword` with efficient substring and regular expression matching. [Autocomplete]({{site.url}}{{site.baseurl}}/field-types/supported-field-types/autocomplete/) |[`completion`]({{site.url}}{{site.baseurl}}/field-types/supported-field-types/completion/): Provides autocomplete functionality through a completion suggester.
[`search_as_you_type`]({{site.url}}{{site.baseurl}}/field-types/supported-field-types/search-as-you-type/): Provides search-as-you-type functionality using both prefix and infix completion. [Geographic]({{site.url}}{{site.baseurl}}/field-types/supported-field-types/geographic/)| [`geo_point`]({{site.url}}{{site.baseurl}}/field-types/supported-field-types/geo-point/): A geographic point.
[`geo_shape`]({{site.url}}{{site.baseurl}}/field-types/supported-field-types/geo-shape/): A geographic shape. [Rank]({{site.url}}{{site.baseurl}}/field-types/supported-field-types/rank/) | Boosts or decreases the relevance score of documents (`rank_feature`, `rank_features`). k-NN vector | [`knn_vector`]({{site.url}}{{site.baseurl}}/field-types/supported-field-types/knn-vector/): Allows indexing a k-NN vector into OpenSearch and performing different kinds of k-NN search. Percolator | [`percolator`]({{site.url}}{{site.baseurl}}/field-types/supported-field-types/percolator/): Specifies to treat this field as a query. +Derived | [`derived`]({{site.url}}{{site.baseurl}}/field-types/supported-field-types/derived/): Creates new fields dynamically by executing scripts on existing fields. ## Arrays diff --git a/_field-types/supported-field-types/string.md b/_field-types/supported-field-types/string.md index c891f86cf6..00f5df6678 100644 --- a/_field-types/supported-field-types/string.md +++ b/_field-types/supported-field-types/string.md @@ -20,3 +20,5 @@ Field data type | Description [`text`]({{site.url}}{{site.baseurl}}/opensearch/supported-field-types/text/) | A string that is analyzed. Useful for full-text search. [`match_only_text`]({{site.url}}{{site.baseurl}}/field-types/supported-field-types/match-only-text/) | A space-optimized version of a `text` field. [`token_count`]({{site.url}}{{site.baseurl}}/opensearch/supported-field-types/token-count/) | Counts the number of tokens in a string. +[`constant_keyword`]({{site.url}}{{site.baseurl}}/field-types/supported-field-types/constant-keyword/) | Similar to `keyword` but uses a single value for all documents. +[`wildcard`]({{site.url}}{{site.baseurl}}/field-types/supported-field-types/wildcard/) | A variation of `keyword` with efficient substring and regular expression matching. diff --git a/_field-types/supported-field-types/wildcard.md b/_field-types/supported-field-types/wildcard.md new file mode 100644 index 0000000000..c438f35c62 --- /dev/null +++ b/_field-types/supported-field-types/wildcard.md @@ -0,0 +1,50 @@ +--- +layout: default +title: Wildcard +nav_order: 62 +has_children: false +parent: String field types +grand_parent: Supported field types +--- + +# Wildcard field type + +A `wildcard` field is a variant of a `keyword` field designed for arbitrary substring and regular expression matching. + +Use a `wildcard` field when your content consists of "strings of characters" and not "text". Examples include unstructured log lines and computer code. + +The `wildcard` field type is indexed differently from the `keyword` field type. Whereas `keyword` fields write the original field value to the index, the `wildcard` field type splits the field value into substrings with a length that is less than or equal to 3 and writes the substrings to the index. For example, the string `test` is split into strings `t`, `te`, `tes`, `e`, `es`, and `est`. + +At search time, required substrings from the query pattern are matched against the index to produce candidate documents, which are then filtered according to the pattern in the query. For example, for the search term `test`, OpenSearch performs an indexed search for `tes AND est`. If the search term contains less than three characters, OpenSearch uses character substrings that are one or two characters long. For each matching document, if the source value is `test`, then the document is returned in the results. This excludes false positive values like `nikola tesla felt alternating current was best`. + +In general, exact match queries (like [`term`]({{site.url}}{{site.baseurl}}/query-dsl/term/term/) or [`terms`]({{site.url}}{{site.baseurl}}/query-dsl/term/term/) queries) perform less effectively on `wildcard` fields than on `keyword` fields, while [`wildcard`]({{site.url}}{{site.baseurl}}/query-dsl/term/wildcard/), [`prefix`]({{site.url}}{{site.baseurl}}/query-dsl/term/prefix/), and [`regexp`]({{site.url}}{{site.baseurl}}/query-dsl/term/regexp/) queries perform better on `wildcard` fields. +{: .tip} + +## Example + +Create a mapping with a `wildcard` field: + +```json +PUT logs +{ + "mappings" : { + "properties" : { + "log_line" : { + "type" : "wildcard" + } + } + } +} +``` +{% include copy-curl.html %} + +## Parameters + +The following table lists all parameters available for `wildcard` fields. + +Parameter | Description +:--- | :--- +`doc_values` | A Boolean value that specifies whether the field should be stored on disk so that it can be used for aggregations, sorting, or scripting. Default is `false`. +`ignore_above` | Any string longer than this integer value should not be indexed. Default is `2147483647`. +`normalizer` | The normalizer used to preprocess values for indexing and search. By default, no normalization occurs and the original value is used. You may use the `lowercase` normalizer to perform case-insentive matching on the field. +`null_value` | A value to be used in place of `null`. Must be of the same type as the field. If this parameter is not specified, then the field is treated as missing when its value is `null`. Default is `null`. diff --git a/_getting-started/quickstart.md b/_getting-started/quickstart.md index 5ef783959a..78104b1913 100644 --- a/_getting-started/quickstart.md +++ b/_getting-started/quickstart.md @@ -3,6 +3,7 @@ layout: default title: Installation quickstart nav_order: 3 redirect_from: + - /about/quickstart/ - /opensearch/install/quickstart/ - /quickstart/ --- @@ -66,7 +67,7 @@ You'll need a special file, called a Compose file, that Docker Compose uses to d ``` {% include copy.html %} -1. In your terminal application, navigate to the directory containing the `docker-compose.yml` file you downloaded and run the following command to create and start the cluster as a background process: +1. In your terminal application, navigate to the directory containing the `docker-compose.yml` file you downloaded, [set up a custom admin password]({{site.url}}{{site.baseurl}}/install-and-configure/install-opensearch/docker/#setting-a-custom-admin-password), and run the following command to create and start the cluster as a background process: ```bash docker-compose up -d diff --git a/_getting-started/security.md b/_getting-started/security.md new file mode 100644 index 0000000000..cc5315e9fd --- /dev/null +++ b/_getting-started/security.md @@ -0,0 +1,198 @@ +--- +layout: default +title: Getting started with OpenSearch security +nav_order: 60 +--- + +# Getting started with OpenSearch security + +The demo configuration is the most straightforward way to get started with OpenSearch security. OpenSearch comes bundled with a number of useful scripts, including `install_demo_configuration.sh` (or `install_demo_configuration.bat` for Windows). + +This script is located in `plugins/opensearch-security/tools` and performs the following actions: + +- Creates demo certificates for TLS encryption on both the transport and REST layers. +- Configures demo users, roles, and role mappings. +- Configures the Security plugin to use an internal database for authentication and authorization. +- Updates the `opensearch.yml` file with the basic configuration needed to start the cluster. + +You can find more information about the demo configuration and how to quickly get started at [Setting up a demo configuration]({{site.url}}{{site.baseurl}}/security/configuration/demo-configuration/). +{: .note} + +Certain aspects of this configuration, such as demo certificates and default passwords, should never be used in production. These parts of the demo configuration should be replaced with your custom information before proceeding to production. +{: .warning} + +## Setting up the demo configuration + +Prior to running the `install_demo_configuration.sh` script, you must create an environment variable named `OPENSEARCH_INITIAL_ADMIN_PASSWORD` with a strong password. This will be used as the password for the admin user to authenticate with OpenSearch. Use the online tool [_Zxcvbn_](https://lowe.github.io/tryzxcvbn/) to test the strength of any password. After this, you can execute `install_demo_configuration.sh` and follow the terminal prompt to enter necessary details. + +After the script is executed, you can start OpenSearch and test the configuration by running the following command: + +``` +curl -k -XGET -u admin: https://:9200 +``` +{% include copy.html %} + +You should see output similar to the following: + +``` +{ + "name" : "smoketestnode", + "cluster_name" : "opensearch", + "cluster_uuid" : "0a5DYAk0Rbi14wqT3TqMiQ", + "version" : { + "distribution" : "opensearch", + "number" : "2.13.0", + "build_type" : "tar", + "build_hash" : "7ec678d1b7c87d6e779fdef94e33623e1f1e2647", + "build_date" : "2024-03-26T00:04:51.025238748Z", + "build_snapshot" : false, + "lucene_version" : "9.10.0", + "minimum_wire_compatibility_version" : "7.10.0", + "minimum_index_compatibility_version" : "7.0.0" + }, + "tagline" : "The OpenSearch Project: https://opensearch.org/" +} +``` + +## Setting up OpenSearch Dashboards + +In order to quickly get started with OpenSearch Dashboards, you can add the following configuration to `opensearch_dashboards.yml`: + +``` +opensearch.hosts: [https://localhost:9200] +opensearch.ssl.verificationMode: none +opensearch.username: kibanaserver +opensearch.password: kibanaserver +opensearch.requestHeadersWhitelist: [authorization, securitytenant] + +opensearch_security.multitenancy.enabled: true +opensearch_security.multitenancy.tenants.preferred: [Private, Global] +opensearch_security.readonly_mode.roles: [kibana_read_only] +# Use this setting if you are running opensearch-dashboards without https +opensearch_security.cookie.secure: false +``` +{% include copy.html %} + +You can start the binary or service, depending on which method was used to install OpenSearch and OpenSearch Dashboards. + +When using binary, you need to supply `--no-base-path` to `yarn start` command to set a URL without a base path. If this is not set, a random three-letter base path will be added. +{: .note} + +After starting OpenSearch Dashboards, you should see the following two log lines: + +``` +[info][listening] Server running at http://localhost:5601 +[info][server][OpenSearchDashboards][http] http server running at http://localhost:5601 +``` +{% include copy.html %} + +You can now access OpenSearch Dashboards using http://localhost:5601 in your browser. Use the username `admin` and the password that was configured in the `OPENSEARCH_INITIAL_ADMIN_PASSWORD` environment variable. + +# Adding users + +There are three ways to add users, roles, and other security-related configurations: + + - Updating appropriate configuration files (`internal_users.yml` for adding/updating/removing users) + - Using the API + - Using the OpenSearch Dashboards UI + +Security configuration files are located in the `config/opensearch-security` directory. +{: .note} + +You can add an OpenSearch Dashboards user by updating the `internal_users.yml` file with the following settings: + +``` +test-user: + hash: "$2y$12$CkxFoTAJKsZaWv/m8VoZ6ePG3DBeBTAvoo4xA2P21VCS9w2RYumsG" + backend_roles: + - "test-backend-role" + - "kibanauser" + description: "test user user" +``` +{% include copy.html %} + +The `hash` string is generated using the `hash.sh` script located in the `plugins/opensearch-security/tools/` directory. In this case, the hash of the string `secretpassword` was used. + +Note the use of the built-in backend role `kibanauser`, which provides the user permissions needed to navigate OpenSearch Dashboards. + +## Creating roles + +Roles contained in `roles.yml` use the following structure: + +``` +: + cluster_permissions: + - + index_permissions: + - index_patterns: + - + allowed_actions: + - +``` +{% include copy.html %} + +Using this structure, you can configure a new role to provide access to specific indexes, such as the role configured in the following example: + +``` +human_resources: + index_permissions: + - index_patterns: + - "humanresources" + allowed_actions: + - "READ" +``` +{% include copy.html %} + +Note that the cluster permissions are not listed in this example because these are provided by the built-in role `kibana_user`, which is already mapped using the `kibanauser` backend role. + + +## Mapping users to roles + +When a user logs in to OpenSearch, they need to be mapped to the appropriate role in order to obtain the correct permissions. This mapping is performed using the `roles_mapping.yml` file with the following structure: + +``` +: + users: + - + - ... + backend_roles: + - +``` +{% include copy.html %} + +In order to map the newly created user `test-user` to the role `human_resources`, you can use the following configuration in the `roles_mapping.yml` file: + +``` +human_resources: + backend_roles: + - test-backend-role +``` +{% include copy.html %} + +As an additional example, the `roles_mappings.yml` file includes the backend role `kibanauser` that has been mapped to the `kibana_user` role: + +``` +kibana_user: + reserved: false + backend_roles: + - "kibanauser" + description: "Maps kibanauser to kibana_user" +``` +{% include copy.html %} + +## Uploading the configuration to a security index + +The final step in configuring a user, role, or any other security configuration is uploading it to a OpenSearch security index. Only updating the files, without uploading them, will not change the configuration of an already running OpenSearch cluster. + +To upload a configuration, the following command can be used with the admin certificate that was generated during `install_demo_configuration.sh` execution: + +``` +./plugins/opensearch-security/tools/securityadmin.sh -cd "config/opensearch-security" -icl -key "../kirk-key.pem" -cert "../kirk.pem" -cacert "../root-ca.pem" -nhnv +``` +{% include copy.html %} + +## Next steps + +The [Best practices for OpenSearch security]({{site.url}}{{site.baseurl}}/security/configuration/best-practices/) guide covers 10 things to consider when getting started with OpenSearch security. + +The [Security configuration]({{site.url}}{{site.baseurl}}/security/configuration/index/) overview provides the basic steps for setting up security in your OpenSearch implementation and includes links to information about customizing security for your business needs. \ No newline at end of file diff --git a/_im-plugin/data-streams.md b/_im-plugin/data-streams.md index d59526b7b8..c2b1449afc 100644 --- a/_im-plugin/data-streams.md +++ b/_im-plugin/data-streams.md @@ -2,6 +2,8 @@ layout: default title: Data streams nav_order: 13 +redirect_from: + - /opensearch/data-streams/ --- # Data streams diff --git a/_im-plugin/reindex-data.md b/_im-plugin/reindex-data.md index a766589b84..6d95883d7a 100644 --- a/_im-plugin/reindex-data.md +++ b/_im-plugin/reindex-data.md @@ -204,8 +204,8 @@ PUT _ingest/pipeline/pipeline-test "field": "text", "separator": "\\s+", "target_field": "word" - }, - } + } + }, { "script": { "lang": "painless", @@ -227,7 +227,7 @@ After creating a pipeline, you can use the `reindex` operation: POST _reindex { "source": { - "index": "source", + "index": "source" }, "dest": { "index": "destination", diff --git a/_ingest-pipelines/processors/fail.md b/_ingest-pipelines/processors/fail.md new file mode 100644 index 0000000000..e529fee799 --- /dev/null +++ b/_ingest-pipelines/processors/fail.md @@ -0,0 +1,154 @@ +--- +layout: default +title: Fail +parent: Ingest processors +nav_order: 100 +--- + +# Fail processor + +The `fail` processor is useful for performing data transformation and enrichment during the indexing process. The primary use case for the `fail` processor is to fail an indexing operation when certain conditions are met. + +The following is the syntax for the `fail` processor: + +```json +"fail": { + "if": "ctx.foo == 'bar'", + "message": "Custom error message" + } +``` +{% include copy-curl.html %} + +## Configuration parameters + +The following table lists the required and optional parameters for the `fail` processor. + +Parameter | Required/Optional | Description | +|-----------|-----------|-----------| +`message` | Required | A custom error message to be included in the failure response. +`description` | Optional | A brief description of the processor. | +`if` | Optional | A condition for running the processor. | +`ignore_failure` | Optional | Specifies whether the processor continues execution even if it encounters an error. If set to `true`, then failures are ignored. Default is `false`. | +`on_failure` | Optional | A list of processors to run if the processor fails. | +`tag` | Optional | An identifier tag for the processor. Useful for debugging in order to distinguish between processors of the same type. | + +## Using the processor + +Follow these steps to use the processor in a pipeline. + +### Step 1: Create a pipeline + +The following query creates a pipeline, named `fail-log-pipeline`, that uses the `fail` processor to intentionally fail the pipeline execution for log events: + +```json +PUT _ingest/pipeline/fail-log-pipeline +{ + "description": "A pipeline to test the fail processor for log events", + "processors": [ + { + "fail": { + "if": "ctx.user_info.contains('password') || ctx.user_info.contains('credit card')", + "message": "Document containing personally identifiable information (PII) cannot be indexed!" + } + } + ] +} +``` +{% include copy-curl.html %} + +### Step 2 (Optional): Test the pipeline + +It is recommended that you test your pipeline before you ingest documents. +{: .tip} + +To test the pipeline, run the following query: + +```json +POST _ingest/pipeline/fail-log-pipeline/_simulate +{ + "docs": [ + { + "_source": { + "user_info": "Sensitive information including credit card" + } + } + ] +} +``` +{% include copy-curl.html %} + +#### Response + +The following example response confirms that the pipeline is working as expected: + +```json +{ + "docs": [ + { + "error": { + "root_cause": [ + { + "type": "fail_processor_exception", + "reason": "Document containing personally identifiable information (PII) cannot be indexed!" + } + ], + "type": "fail_processor_exception", + "reason": "Document containing personally identifiable information (PII) cannot be indexed!" + } + } + ] +} +``` +{% include copy-curl.html %} + +### Step 3: Ingest a document + +The following query ingests a document into an index named `testindex1`: + +```json +PUT testindex1/_doc/1?pipeline=fail-log-pipeline +{ + "user_info": "Sensitive information including credit card" +} +``` +{% include copy-curl.html %} + +#### Response + +The request fails to index the log event into the index `testindex1` due to the string `credit card` being present in `user_info`. The following response includes the custom error message specified in the fail processor: + +```json + + "error": { + "root_cause": [ + { + "type": "fail_processor_exception", + "reason": "Document containing personally identifiable information (PII) cannot be indexed!" + } + ], + "type": "fail_processor_exception", + "reason": "Document containing personally identifiable information (PII) cannot be indexed!" + }, + "status": 500 +} +``` +{% include copy-curl.html %} + +### Step 4 (Optional): Retrieve the document + +Because the log event was not indexed due to the pipeline failure, attempting to retrieve it results in the document not found error `"found": false`: + +```json +GET testindex1/_doc/1 +``` +{% include copy-curl.html %} + +#### Document error example + +```json +{ + "_index": "testindex1", + "_id": "1", + "found": false +} +``` diff --git a/_ingest-pipelines/processors/foreach.md b/_ingest-pipelines/processors/foreach.md new file mode 100644 index 0000000000..d0f962e618 --- /dev/null +++ b/_ingest-pipelines/processors/foreach.md @@ -0,0 +1,211 @@ +--- +layout: default +title: Foreach +parent: Ingest processors +nav_order: 110 +--- + + +# Foreach processor + + +The `foreach` processor is used to iterate over a list of values in an input document and apply a transformation to each value. This can be useful for tasks like processing all the elements in an array consistently, such as converting all elements in a string to lowercase or uppercase. + +The following is the syntax for the `foreach` processor: + +```json +{ + "foreach": { + "field": "", + "processor": { + "": { + "": "" + } + } + } +} +``` +{% include copy-curl.html %} + +## Configuration parameters + +The following table lists the required and optional parameters for the `foreach` processor. + +Parameter | Required/Optional | Description | +|-----------|-----------|-----------| +`field` | Required | The array field to iterate over. +`processor` | Required | The processor to execute against each field. +`ignore_missing` | Optional | If `true` and the specified field does not exist or is null, then the processor will quietly exit without modifying the document. +`description` | Optional | A brief description of the processor. +`if` | Optional | A condition for running the processor. +`ignore_failure` | Optional | Specifies whether the processor continues execution even if it encounters an error. If set to `true`, then failures are ignored. Default is `false`. +`on_failure` | Optional | A list of processors to run if the processor fails. +`tag` | Optional | An identifier tag for the processor. Useful for debugging in order to distinguish between processors of the same type. + +## Using the processor + +Follow these steps to use the processor in a pipeline. + +### Step 1: Create a pipeline + +The following query creates a pipeline named `test-foreach` that uses the `foreach` processor to iterate over each element in the `protocols` field: + +```json +PUT _ingest/pipeline/test-foreach +{ + "description": "Lowercase all the elements in an array", + "processors": [ + { + "foreach": { + "field": "protocols", + "processor": { + "lowercase": { + "field": "_ingest._value" + } + } + } +``` +{% include copy-curl.html %} + +### Step 2 (Optional): Test the pipeline + +It is recommended that you test your pipeline before you ingest documents. +{: .tip} + +To test the pipeline, run the following query: + +```json +POST _ingest/pipeline/test-foreach/_simulate +{ + "docs": [ + { + "_index": "testindex1", + "_id": "1", + "_source": { + "protocols": ["HTTP","HTTPS","TCP","UDP"] + } + } + ] +} +``` +{% include copy-curl.html %} + +#### Response + +The following example response confirms that the pipeline is working as expected, showing that the four elements have been lowercased: + +```json +{ + "docs": [ + { + "doc": { + "_index": "testindex1", + "_id": "1", + "_source": { + "protocols": [ + "http", + "https", + "tcp", + "udp" + ] + }, + "_ingest": { + "_value": null, + "timestamp": "2024-05-23T02:44:10.8201Z" + } + } + } + ] +} + +``` +{% include copy-curl.html %} + +### Step 3: Ingest a document + +The following query ingests a document into an index named `testindex1`: + +```json +POST testindex1/_doc/1?pipeline=test-foreach +{ + "protocols": ["HTTP","HTTPS","TCP","UDP"] +} +``` +{% include copy-curl.html %} + +#### Response + +The request indexes the document into the index `testindex1` and applies the pipeline before indexing: + +```json +{ + "_index": "testindex1", + "_id": "1", + "_version": 6, + "result": "created", + "_shards": { + "total": 2, + "successful": 1, + "failed": 0 + }, + "_seq_no": 5, + "_primary_term": 67 +} +``` +{% include copy-curl.html %} + +### Step 4 (Optional): Retrieve the document + +To retrieve the document, run the following query: + +```json +GET testindex1/_doc/1 +``` +{% include copy-curl.html %} + +#### Response + +The response shows the document with the extracted JSON data from the `users` field: + +```json +{ + "_index": "testindex1", + "_id": "1", + "_version": 6, + "_seq_no": 5, + "_primary_term": 67, + "found": true, + "_source": { + "protocols": [ + "http", + "https", + "tcp", + "udp" + ] + } +} + +{ + "docs": [ + { + "doc": { + "_index": "testindex1", + "_id": "1", + "_source": { + "protocols": [ + "http", + "https", + "tcp", + "udp" + ] + }, + "_ingest": { + "_value": null, + "timestamp": "2024-05-23T02:44:10.8201Z" + } + } + } + ] +} +``` +{% include copy-curl.html %} diff --git a/_ingest-pipelines/processors/gsub.md b/_ingest-pipelines/processors/gsub.md new file mode 100644 index 0000000000..1619d98f81 --- /dev/null +++ b/_ingest-pipelines/processors/gsub.md @@ -0,0 +1,170 @@ +--- +layout: default +title: gsub +parent: Ingest processors +nav_order: 130 +--- + +# Gsub processor + +The `gsub` processor performs a regular expression search-and-replace operation on string fields in incoming documents. If the field contains an array of strings, the operation is applied to all elements in the array. However, if the field contains non-string values, the processor throws an exception. Use cases for the `gsub` processor include removing sensitive information from log messages or user-generated content, normalizing data formats or conventions (for example, converting date formats, removing special characters), and extracting or transforming substrings from field values for further processing or analysis. + +The following is the syntax for the `gsub` processor: + +```json +"gsub": { + "field": "field_name", + "pattern": "regex_pattern", + "replacement": "replacement_string" +} +``` +{% include copy-curl.html %} + +## Configuration parameters + +The following table lists the required and optional parameters for the `gsub` processor. + +Parameter | Required/Optional | Description | +|-----------|-----------|-----------| +`field` | Required | The field to apply the replacement to. +`pattern` | Required | The pattern to be replaced. +`replacement` | Required | The string that will replace the matching patterns. +`target_field` | Optional | The name of the field in which to store the parsed data. If `target_field` is not specified, the parsed data replaces the original data in the `field` field. Default is `field`. +`if` | Optional | A condition for running the processor. +`ignore_missing` | Optional | Specifies whether the processor should ignore documents that do not contain the specified field. Default is `false`. +`ignore_failure` | Optional | Specifies whether the processor continues execution even if it encounters an error. If set to `true`, then failures are ignored. Default is `false`. +`on_failure` | Optional | A list of processors to run if the processor fails. +`tag` | Optional | An identifier tag for the processor. Useful for debugging in order to distinguish between processors of the same type. + +## Using the processor + +Follow these steps to use the processor in a pipeline. + +### Step 1: Create a pipeline + +The following query creates a pipeline named `gsub_pipeline` that uses the `gsub` processor to replace all occurrences of the word `error` with the word `warning` in the `message` field: + +```json +PUT _ingest/pipeline/gsub_pipeline +{ + "description": "Replaces 'error' with 'warning' in the 'message' field", + "processors": [ + { + "gsub": { + "field": "message", + "pattern": "error", + "replacement": "warning" + } + } + ] +} +``` +{% include copy-curl.html %} + +### Step 2 (Optional): Test the pipeline + +It is recommended that you test your pipeline before you ingest documents. +{: .tip} + +To test the pipeline, run the following query: + +```json +POST _ingest/pipeline/gsub_pipeline/_simulate +{ + "docs": [ + { + "_source": { + "message": "This is an error message" + } + } + ] +} +``` +{% include copy-curl.html %} + +#### Response + +The following response confirms that the pipeline is working as expected: + +```json +{ + "docs": [ + { + "doc": { + "_index": "_index", + "_id": "_id", + "_source": { + "message": "This is an warning message" + }, + "_ingest": { + "timestamp": "2024-05-22T19:47:00.645687211Z" + } + } + } + ] +} +``` +{% include copy-curl.html %} + +### Step 3: Ingest a document + +The following query ingests a document into an index named `logs`: + +```json +PUT logs/_doc/1?pipeline=gsub_pipeline +{ + "message": "This is an error message" +} +``` +{% include copy-curl.html %} + +#### Response + +The following response shows that the request indexed the document into the index named `logs` and that the `gsub` processor replaced all occurrences of the word `error` with the word `warning` in the `message` field: + +```json +{ + "_index": "logs", + "_id": "1", + "_version": 1, + "result": "created", + "_shards": { + "total": 2, + "successful": 1, + "failed": 0 + }, + "_seq_no": 0, + "_primary_term": 1 +} +``` +{% include copy-curl.html %} + +### Step 4 (Optional): Retrieve the document + +To retrieve the document, run the following query: + +```json +GET logs/_doc/1 +``` +{% include copy-curl.html %} + +#### Response + +The following response shows the document with the modified `message` field value: + +```json +{ + "_index": "logs", + "_id": "1", + "_version": 1, + "_seq_no": 0, + "_primary_term": 1, + "found": true, + "_source": { + "message": "This is an warning message" + } +} +``` +{% include copy-curl.html %} + + diff --git a/_ingest-pipelines/processors/html-strip.md b/_ingest-pipelines/processors/html-strip.md new file mode 100644 index 0000000000..ac33c45eae --- /dev/null +++ b/_ingest-pipelines/processors/html-strip.md @@ -0,0 +1,169 @@ +--- +layout: default +title: HTML strip +parent: Ingest processors +nav_order: 140 +--- + +# HTML strip processor + +The `html_strip` processor removes HTML tags from string fields in incoming documents. This processor is useful when indexing data from webpages or other sources that may contain HTML markup. HTML tags are replaced with newline characters (`\n`). + +The following is the syntax for the `html_strip` processor: + +```json +{ + "html_strip": { + "field": "webpage" + } +} +``` +{% include copy-curl.html %} + +## Configuration parameters + +The following table lists the required and optional parameters for the `html_strip` processor. + +Parameter | Required/Optional | Description | +|-----------|-----------|-----------| +`field` | Required | The string field from which to remove HTML tags. +`target_field` | Optional | The field that receives the plain text version after stripping HTML tags. If not specified, then the field is updated in-place. +`ignore_missing` | Optional | Specifies whether the processor should ignore documents that do not contain the specified field. Default is `false`. +`description` | Optional | A description of the processor's purpose or configuration. +`if` | Optional | Specifies to conditionally execute the processor. +`ignore_failure` | Optional | Specifies to ignore processor failures. See [Handling pipeline failures]({{site.url}}{{site.baseurl}}/ingest-pipelines/pipeline-failures/). +`on_failure` | Optional | Specifies a list of processors to run if the processor fails during execution. These processors are executed in the order they are specified. See [Handling pipeline failures]({{site.url}}{{site.baseurl}}/ingest-pipelines/pipeline-failures/). +`tag` | Optional | An identifier tag for the processor. Useful for debugging in order to distinguish between processors of the same type. + +## Using the processor + +Follow these steps to use the processor in a pipeline. + +### Step 1: Create a pipeline + +The following query creates a pipeline named `strip-html-pipeline` that uses the `html_strip` processor to remove HTML tags from the description field and store the processed value in a new field named `cleaned_description`: + +```json +PUT _ingest/pipeline/strip-html-pipeline +{ + "description": "A pipeline to strip HTML from description field", + "processors": [ + { + "html_strip": { + "field": "description", + "target_field": "cleaned_description" + } + } + ] +} +``` +{% include copy-curl.html %} + +### Step 2 (Optional): Test the pipeline + +It is recommended that you test your pipeline before you ingest documents. +{: .tip} + +To test the pipeline, run the following query: + +```json +POST _ingest/pipeline/strip-html-pipeline/_simulate +{ + "docs": [ + { + "_source": { + "description": "This is a test description with some HTML tags." + } + } + ] +} +``` +{% include copy-curl.html %} + +#### Response + +The following example response confirms that the pipeline is working as expected: + +```json +{ + "docs": [ + { + "doc": { + "_index": "_index", + "_id": "_id", + "_source": { + "description": "This is a test description with some HTML tags.", + "cleaned_description": "This is a test description with some HTML tags." + }, + "_ingest": { + "timestamp": "2024-05-22T21:46:11.227974965Z" + } + } + } + ] +} +``` +{% include copy-curl.html %} + +### Step 3: Ingest a document + +The following query ingests a document into an index named `products`: + +```json +PUT products/_doc/1?pipeline=strip-html-pipeline +{ + "name": "Product 1", + "description": "This is a test product with some HTML tags." +} +``` +{% include copy-curl.html %} + +#### Response + +The response shows that the request has indexed the document into the index `products` and will index all documents with the `description` field containing HTML tags while storing the plain text version in the `cleaned_description` field: + +```json +{ + "_index": "products", + "_id": "1", + "_version": 1, + "result": "created", + "_shards": { + "total": 2, + "successful": 1, + "failed": 0 + }, + "_seq_no": 0, + "_primary_term": 1 +} +``` +{% include copy-curl.html %} + +### Step 4 (Optional): Retrieve the document + +To retrieve the document, run the following query: + +```json +GET products/_doc/1 +``` +{% include copy-curl.html %} + +#### Response + +The response includes both the original `description` field and the `cleaned_description` field with HTML tags removed: + +```json +{ + "_index": "products", + "_id": "1", + "_version": 1, + "_seq_no": 0, + "_primary_term": 1, + "found": true, + "_source": { + "cleaned_description": "This is a test product with some HTML tags.", + "name": "Product 1", + "description": "This is a test product with some HTML tags." + } +} +``` \ No newline at end of file diff --git a/_ingest-pipelines/processors/index-processors.md b/_ingest-pipelines/processors/index-processors.md index 0c6f2ca4a8..79f30524d6 100644 --- a/_ingest-pipelines/processors/index-processors.md +++ b/_ingest-pipelines/processors/index-processors.md @@ -24,7 +24,7 @@ To set up and deploy ingest processors, make sure you have the necessary permiss ## Supported processors -Processor types and their required or optional parameters vary depending on your specific use case. OpenSearch supports the following ingest processors. For tutorials on using these processors in an OpenSerch pipeline, go to each processor's respective documentation. +Processor types and their required or optional parameters vary depending on your specific use case. OpenSearch supports the following ingest processors. For tutorials on using these processors in an OpenSearch pipeline, go to each processor's respective documentation. Processor type | Description :--- | :--- @@ -67,3 +67,7 @@ Processor type | Description `uppercase` | Converts text in a specific field to uppercase letters. `urldecode` | Decodes a string from URL-encoded format. `user_agent` | Extracts details from the user agent sent by a browser to its web requests. + +## Batch-enabled processors + +Some processors support batch ingestion---they can process multiple documents at the same time as a batch. These batch-enabled processors usually provide better performance when using batch processing. For batch processing, use the [Bulk API]({{site.url}}{{site.baseurl}}/api-reference/document-apis/bulk/) and provide a `batch_size` parameter. All batch-enabled processors have a batch mode and a single-document mode. When you ingest documents using the `PUT` method, the processor functions in single-document mode and processes documents in series. Currently, only the `text_embedding` and `sparse_encoding` processors are batch enabled. All other processors process documents one at a time. diff --git a/_ingest-pipelines/processors/join.md b/_ingest-pipelines/processors/join.md new file mode 100644 index 0000000000..c2cdcfe4de --- /dev/null +++ b/_ingest-pipelines/processors/join.md @@ -0,0 +1,135 @@ +--- +layout: default +title: Join +parent: Ingest processors +nav_order: 160 +--- + +# Join processor + +The `join` processor concatenates the elements of an array into a single string value, using a specified separator between each element. It throws an exception if the provided input is not an array. + +The following is the syntax for the `join` processor: + +```json +{ + "join": { + "field": "field_name", + "separator": "separator_string" + } +} +``` +{% include copy-curl.html %} + +## Configuration parameters + +The following table lists the required and optional parameters for the `join` processor. + +Parameter | Required/Optional | Description | +|-----------|-----------|-----------| +`field` | Required | The name of the field to which the join operator is applied. Must be an array. +`separator` | Required | A string separator to use when joining field values. If not specified, then the values are concatenated without a separator. +`target_field` | Optional | The field to assign the cleaned value to. If not specified, then the field is updated in place. +`description` | Optional | A description of the processor's purpose or configuration. +`if` | Optional | Specifies to conditionally execute the processor. +`ignore_failure` | Optional | Specifies to ignore failures for the processor. See [Handling pipeline failures]({{site.url}}{{site.baseurl}}/ingest-pipelines/pipeline-failures/). +`on_failure` | Optional | Specifies to handle failures for the processor. See [Handling pipeline failures]({{site.url}}{{site.baseurl}}/ingest-pipelines/pipeline-failures/). +`tag` | Optional | An identifier for the processor. Useful for debugging and metrics. + +## Using the processor + +Follow these steps to use the processor in a pipeline. + +### Step 1: Create a pipeline + +The following query creates a pipeline named `example-join-pipeline` that uses the `join` processor to concatenate all the values of the `uri` field, separating them with the specified separator `/`: + +```json +PUT _ingest/pipeline/example-join-pipeline +{ + "description": "Example pipeline using the join processor", + "processors": [ + { + "join": { + "field": "uri", + "separator": "/" + } + } + ] +} +``` +{% include copy-curl.html %} + +### Step 2 (Optional): Test the pipeline + +It is recommended that you test your pipeline before you ingest documents. +{: .tip} + +To test the pipeline, run the following query: + +```json +POST _ingest/pipeline/example-join-pipeline/_simulate +{ + "docs": [ + { + "_source": { + "uri": [ + "app", + "home", + "overview" + ] + } + } + ] +} +``` +{% include copy-curl.html %} + +#### Response + +The following example response confirms that the pipeline is working as expected: + +```json +{ + "docs": [ + { + "doc": { + "_index": "_index", + "_id": "_id", + "_source": { + "uri": "app/home/overview" + }, + "_ingest": { + "timestamp": "2024-05-24T02:16:01.00659117Z" + } + } + } + ] +} +``` +{% include copy-curl.html %} + +### Step 3: Ingest a document + +The following query ingests a document into an index named `testindex1`: + +```json +POST testindex1/_doc/1?pipeline=example-join-pipeline +{ + "uri": [ + "app", + "home", + "overview" + ] +} +``` +{% include copy-curl.html %} + +### Step 4 (Optional): Retrieve the document + +To retrieve the document, run the following query: + +```json +GET testindex1/_doc/1 +``` +{% include copy-curl.html %} diff --git a/_ingest-pipelines/processors/json.md b/_ingest-pipelines/processors/json.md new file mode 100644 index 0000000000..d251533e27 --- /dev/null +++ b/_ingest-pipelines/processors/json.md @@ -0,0 +1,199 @@ +--- +layout: default +title: JSON +parent: Ingest processors +nav_order: 170 +--- + +# JSON processor + +The `json` processor serializes a string value field into a map of maps, which can be useful for various data processing and enrichment tasks. + +The following is the syntax for the `json` processor: + +```json +{ + "processor": { + "json": { + "field": "", + "target_field": "", + "add_to_root": + } + } +} +``` +{% include copy-curl.html %} + +## Configuration parameters + +The following table lists the required and optional parameters for the `json` processor. + +Parameter | Required/Optional | Description | +|-----------|-----------|-----------| +`field` | Required | The name of the field containing the JSON-formatted string to be deserialized. +`target_field` | Optional | The name of the field in which the deserialized JSON data is stored. When not provided, the data is stored in the `field` field. If `target_field` exists, its existing value is overwritten with the new JSON data. +`add_to_root` | Optional | A Boolean flag that determines whether the deserialized JSON data should be added to the root of the document (`true`) or stored in the target_field (`false`). If `add_to_root` is `true`, then `target-field` is invalid. Default value is `false`. +`description` | Optional | A description of the processor's purpose or configuration. +`if` | Optional | Specifies to conditionally execute the processor. +`ignore_failure` | Optional | Specifies to ignore processor failures. See [Handling pipeline failures]({{site.url}}{{site.baseurl}}/ingest-pipelines/pipeline-failures/). +`on_failure`| Optional | Specifies a list of processors to run if the processor fails during execution. These processors are executed in the order they are specified. +`tag` | Optional | An identifier tag for the processor. Useful for debugging in order to distinguish between processors of the same type. + +## Using the processor + +Follow these steps to use the processor in a pipeline. + +### Step 1: Create a pipeline + +The following query creates a pipeline named `my-json-pipeline` that uses the `json` processor to process JSON data and enrich the documents with additional information: + +```json +PUT _ingest/pipeline/my-json-pipeline +{ + "description": "Example pipeline using the JsonProcessor", + "processors": [ + { + "json": { + "field": "raw_data", + "target_field": "parsed_data" + "on_failure": [ + { + "set": { + "field": "error_message", + "value": "Failed to parse JSON data" + } + }, + { + "fail": { + "message": "Failed to process JSON data" + } + } + ] + } + }, + { + "set": { + "field": "processed_timestamp", + "value": "{{_ingest.timestamp}}" + } + } + ] +} +``` +{% include copy-curl.html %} + +### Step 2 (Optional): Test the pipeline + +It is recommended that you test your pipeline before you ingest documents. +{: .tip} + +To test the pipeline, run the following query: + +```json +POST _ingest/pipeline/my-json-pipeline/_simulate +{ + "docs": [ + { + "_source": { + "raw_data": "{\"name\":\"John\",\"age\":30,\"city\":\"New York\"}" + } + }, + { + "_source": { + "raw_data": "{\"name\":\"Jane\",\"age\":25,\"city\":\"Los Angeles\"}" + } + } + ] +} +``` +{% include copy-curl.html %} + +#### Response + +The following example response confirms that the pipeline is working as expected: + +```json +{ + "docs": [ + { + "doc": { + "_index": "_index", + "_id": "_id", + "_source": { + "processed_timestamp": "2024-05-30T15:24:48.064472090Z", + "raw_data": """{"name":"John","age":30,"city":"New York"}""", + "parsed_data": { + "name": "John", + "city": "New York", + "age": 30 + } + }, + "_ingest": { + "timestamp": "2024-05-30T15:24:48.06447209Z" + } + } + }, + { + "doc": { + "_index": "_index", + "_id": "_id", + "_source": { + "processed_timestamp": "2024-05-30T15:24:48.064543006Z", + "raw_data": """{"name":"Jane","age":25,"city":"Los Angeles"}""", + "parsed_data": { + "name": "Jane", + "city": "Los Angeles", + "age": 25 + } + }, + "_ingest": { + "timestamp": "2024-05-30T15:24:48.064543006Z" + } + } + } + ] +} +``` +{% include copy-curl.html %} + +### Step 3: Ingest a document + +The following query ingests a document into an index named `my-index`: + +```json +POST my-index/_doc?pipeline=my-json-pipeline +{ + "raw_data": "{\"name\":\"John\",\"age\":30,\"city\":\"New York\"}" +} +``` +{% include copy-curl.html %} + +#### Response + +The response confirms that the document containing the JSON data from the `raw_data` field was successfully indexed: + +```json +{ + "_index": "my-index", + "_id": "mo8yyo8BwFahnwl9WpxG", + "_version": 1, + "result": "created", + "_shards": { + "total": 2, + "successful": 1, + "failed": 0 + }, + "_seq_no": 3, + "_primary_term": 2 +} +``` +{% include copy-curl.html %} + +### Step 4 (Optional): Retrieve the document + +To retrieve the document, run the following query: + +```json +GET my-index/_doc/1 +``` +{% include copy-curl.html %} diff --git a/_ingest-pipelines/processors/ml-inference.md b/_ingest-pipelines/processors/ml-inference.md index 808f7f974e..1aa22995e1 100644 --- a/_ingest-pipelines/processors/ml-inference.md +++ b/_ingest-pipelines/processors/ml-inference.md @@ -2,17 +2,18 @@ layout: default title: ML inference parent: Ingest processors -nav_order: 240 +nav_order: 215 redirect_from: - /api-reference/ingest-apis/processors/ml-inference/ --- # ML inference processor -The `ml_inference` processor is used to generate inferences from machine learning (ML) models connected to the [OpenSearch ML Commons plugin]({{site.url}}{{site.baseurl}}/ml-commons-plugin/). The inferences are added as new fields to the ingested documents. +The `ml_inference` processor is used to invoke machine learning (ML) models registered in the [OpenSearch ML Commons plugin]({{site.url}}{{site.baseurl}}/ml-commons-plugin/). The model outputs are added as new fields to the ingested documents. **PREREQUISITE**
-Before using the `ml_inference` processor, you must have an ML model connected to your OpenSearch cluster through the ML Commons plugin. For more information, see [Connecting to externally hosted models]({{site.url}}{{site.baseurl}}/ml-commons-plugin/remote-models/index/). +Before using the `ml_inference` processor, you must have either a local ML model hosted on your OpenSearch cluster or an externally hosted model connected to your OpenSearch cluster through the ML Commons plugin. For more information about local models, see [Using ML models within OpenSearch]({{site.url}}{{site.baseurl}}/ml-commons-plugin/using-ml-models/). For more information about externally hosted models, see [Connecting to externally hosted models]({{site.url}}{{site.baseurl}}/ml-commons-plugin/remote-models/index/). +{: .note} ## Syntax @@ -22,19 +23,23 @@ The following is the syntax for the `ml-inference` processor: { "ml_inference": { "model_id": "", + "function_name": "", + "full_response_path": "", + "model_config":{ + "": "" + }, + "model_input": "", "input_map": [ { - "": "" + "": "" } ], "output_map": [ { - "": "" + "": "" } ], - "model_config":{ - "": "" - } + "override": "" } } ``` @@ -44,32 +49,46 @@ The following is the syntax for the `ml-inference` processor: The following table lists the required and optional parameters for the `ml-inference` processor. -| Parameter | Data type | Required/Optional | Description | -|:---|:----------|:---|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `model_id` | String | Required | The ID of the ML model connected to the OpenSearch cluster through the ML Commons plugin. | -| `input_map` | Array | Optional | An array specifying how to map fields from the ingested document to the model's input. If no input mapping is specified, then all fields from the document are used as the model input by default. The `input_map` size indicates the number of prediction tasks. In each map, the key represents the model input field name, and the value specifies the document field used to construct the model input. | -| `input_map.` | String | Optional | The model input field name. | -| `input_map.` | String | Optional | The name of the field from the ingested document to be used as the model's input. | -| `output_map` | Array | Optional | An array specifying how to map the model's output to new fields in the ingested document. | -| `output_map.` | String | Optional | The name of the new field in the ingested document in which the model's output (specified by the `output_key`) is stored. If no output mapping is specified, then all fields from the model prediction output are added to the new document field by default. | -| `output_map.` | String | Optional | The key representing the model output to be stored in the `output_field`. | -| `model_config` | Object | Optional | Custom configuration options for the ML model. | -| `max_prediction_tasks` | Integer | Optional | The maximum number of concurrent prediction tasks that can run during document ingestion. Default is `10`. | -| `description` | String | Optional | A brief description of the processor. | -| `tag` | String | Optional | An identifier tag for the processor. Useful for debugging to distinguish between processors of the same type. | -| `ignore_missing` | Boolean | Optional | If `true` and any of the input fields defined in `input_map` or `output_map` are missing, then the missing fields are ignored. Otherwise, a missing field causes a failure. Default is `false`. | -| `ignore_failure` | Boolean | Optional | If `true` and any exceptions occur, then they are ignored and ingestion continues. Otherwise, an exception occurs and ingestion is canceled. Default is `false`. | +| Parameter | Data type | Required/Optional | Description | +|:--- | :--- | :--- | :--- | +| `model_id` | String | Required | The ID of the ML model used by the processor. | +| `function_name` | String | Optional for externally hosted models

Required for local models | The function name of the ML model configured in the processor. For local models, valid values are `sparse_encoding`, `sparse_tokenize`, `text_embedding`, and `text_similarity`. For externally hosted models, valid value is `remote`. Default is `remote`. | +| `model_config` | Object | Optional | Custom configuration options for the ML model. For more information, see [The `model_config` object]({{site.url}}{{site.baseurl}}/ml-commons-plugin/api/model-apis/register-model/#the-model_config-object). | +| `model_input` | String | Optional for externally hosted models

Required for local models | A template that defines the input field format expected by the model. Each local model type might use a different set of inputs. For externally hosted models, default is `"{ \"parameters\": ${ml_inference.parameters} }`.| +| `input_map` | Array | Optional for externally hosted models

Required for local models | An array specifying how to map ingested document fields to the model input fields. Each element of the array is a map in the `"": ""` format and corresponds to one model invocation for a document field. If no input mapping is specified for an externally hosted model, then all fields from the document are passed to the model directly as input. The `input_map` size indicates the number of times the model is invoked (the number of Predict API requests). | +| `` | String | Optional for externally hosted models

Required for local models | The model input field name. | +| `` | String | Optional for externally hosted models

Required for local models | The name or JSON path of the ingested document field used as the model input. | +| `output_map` | Array | Optional for externally hosted models

Required for local models | An array specifying how to map the model output fields to new fields in the ingested document. Each element of the array is a map in the `"": ""` format.| +| `` | String | Optional for externally hosted models

Required for local models | The name of the new field in the ingested document in which the model's output (specified by `model_output`) is stored. If no output mapping is specified for externally hosted models, then all fields from the model output are added to the new document field. | +| `` | String | Optional for externally hosted models

Required for local models | The name or JSON path of the field in the model output to be stored in the `new_document_field`. | +| `full_response_path` | Boolean | Optional | Set this parameter to `true` if the `model_output_field` contains a full JSON path to the field instead of the field name. The model output will then be fully parsed to get the value of the field. Default is `true` for local models and `false` for externally hosted models. | +| `ignore_missing` | Boolean | Optional | If `true` and any of the input fields defined in the `input_map` or `output_map` are missing, then the missing fields are ignored. Otherwise, a missing field causes a failure. Default is `false`. | +| `ignore_failure` | Boolean | Optional | Specifies whether the processor continues execution even if it encounters an error. If `true`, then any failure is ignored and ingestion continues. If `false`, then any failure causes ingestion to be canceled. Default is `false`. | +| `override` | Boolean | Optional | Relevant if an ingested document already contains a field with the name specified in ``. If `override` is `false`, then the input field is skipped. If `true`, then the existing field value is overridden by the new model output. Default is `false`. | +| `max_prediction_tasks` | Integer | Optional | The maximum number of concurrent model invocations that can run during document ingestion. Default is `10`. | +| `description` | String | Optional | A brief description of the processor. | +| `tag` | String | Optional | An identifier tag for the processor. Useful for debugging to distinguish between processors of the same type. | + +The `input_map` and `output_map` mappings support standard [JSON path](https://github.com/json-path/JsonPath) notation for specifying complex data structures. +{: .note} ## Using the processor -Follow these steps to use the processor in a pipeline. You must provide a model ID when creating the processor. Only remote models are currently supported. For more information about creating remote models, see [Connecting to externally hosted models]({{site.url}}{{site.baseurl}}/ml-commons-plugin/remote-models/index/). +Follow these steps to use the processor in a pipeline. You must provide a model ID when creating the processor. Before testing a pipeline or ingesting the documents using the processor, make sure that the model is successfully deployed. You can check the model state using the [Get Model API]({{site.url}}{{site.baseurl}}/ml-commons-plugin/api/model-apis/get-model/). + +For local models, you must provide a `model_input` field that specifies the model input format. Add any input fields in `model_config` to `model_input`. + +For remote models, the `model_input` field is optional, and its default value is `"{ \"parameters\": ${ml_inference.parameters} }`. + +### Example: Externally hosted model + +The following example configures an `ml_inference` processor with an externally hosted model. **Step 1: Create a pipeline** -The following example creates an ingest pipeline where the model requires an `input` field, produces a `data` field for prediction, and converts the `passage_text` field into text embeddings stored in the `passage_embedding` field. The `input_map` and `output_map` mappings support standard JSON path notation for complex data structures. +The following example creates an ingest pipeline for an externally hosted text embedding model. The model requires an `input` field and generates results in a `data` field. It converts the text in the `passage_text` field into text embeddings and stores the embeddings in the `passage_embedding` field. The `function_name` is not explicitly specified in the processor configuration, so it defaults to `remote`, signifying an externally hosted model: ```json - PUT /_ingest/pipeline/ml_inference_pipeline { "description": "Generate passage_embedding for ingested documents", @@ -94,6 +113,31 @@ PUT /_ingest/pipeline/ml_inference_pipeline ``` {% include copy-curl.html %} +For a Predict API request to an externally hosted model, all fields are usually nested inside the `parameters` object: + +```json +POST /_plugins/_ml/models/cleMb4kBJ1eYAeTMFFg4/_predict +{ + "parameters": { + "input": [ + { + ... + } + ] + } +} +``` + +When specifying the `input_map` for an externally hosted model, you can directly reference the `input` field instead of providing its dot path `parameters.input`: + +```json +"input_map": [ + { + "input": "passage_text" + } +] +``` + **Step 2 (Optional): Test the pipeline** It is recommended that you test your pipeline before you ingest documents. @@ -119,7 +163,7 @@ POST _ingest/pipeline/ml_inference_pipeline/_simulate #### Response -The response confirms that, in addition to the `passage_text` field, the processor has generated text embeddings in the `passage_embedding` field: +The response confirms that the processor has generated text embeddings in the `passage_embedding` field. The document now contains both the `passage_text` and `passage_embedding` fields: ```json { @@ -150,9 +194,263 @@ The response confirms that, in addition to the `passage_text` field, the process Once you have created an ingest pipeline, you need to create an index for ingestion and ingest documents into the index. {: .note} ---- +### Example: Local model + +The following example configures an `ml_inference` processor with a local model. + +**Step 1: Create a pipeline** + +The following example creates an ingest pipeline for the `huggingface/sentence-transformers/all-distilroberta-v1` local model. The model is a sentence transformer [pretrained model]({{site.url}}{{site.baseurl}}/ml-commons-plugin/pretrained-models/#sentence-transformers) hosted in your OpenSearch cluster. + +If you invoke the model using the Predict API, then the request looks like this: + +```json +POST /_plugins/_ml/_predict/text_embedding/cleMb4kBJ1eYAeTMFFg4 +{ + "text_docs":[ "today is sunny"], + "return_number": true, + "target_response": ["sentence_embedding"] +} +``` + +Using this schema, specify the `model_input` as follows: + +```json + "model_input": "{ \"text_docs\": ${input_map.text_docs}, \"return_number\": ${model_config.return_number}, \"target_response\": ${model_config.target_response} }" +``` + +In the `input_map`, map the `book.*.chunk.text.*.context` document field to the `text_docs` field expected by the model: + +```json +"input_map": [ + { + "text_docs": "book.*.chunk.text.*.context" + } +] +``` + +Because you specified the field to convert into embeddings as a JSON path, you need to set the `full_response_path` to `true` so that the full JSON document is parsed to obtain the input field: + +```json +"full_response_path": true +``` + +The documents you index will appear as follows. The text in the `context` field will be used to generate embeddings: + +```json +"book": [ + { + "chunk": { + "text": [ + { + "chapter": "first chapter", + "context": "this is the first part" + } + ] + } + } +] +``` + +The Predict API request returns the following response: + +```json +{ + "inference_results" : [ + { + "output" : [ + { + "name" : "sentence_embedding", + "data_type" : "FLOAT32", + "shape" : [ + 768 + ], + "data" : [ + 0.25517133, + -0.28009856, + 0.48519906, + ... + ] + } + ] + } + ] +} +``` + +The model generates embeddings in the `$.inference_results.*.output.*.data` field. The `output_map` maps this field to the newly created `book.*.chunk.text.*.context_embedding` field in the ingested document: + +```json +"output_map": [ + { + "book.*.chunk.text.*.context_embedding": "$.inference_results.*.output.*.data" + } +] +``` + +To configure an `ml_inference` processor with a local model, specify the `function_name` explicitly. In this example, `function_name` is `text_embedding`. For information about valid `function_name` values, see [Configuration parameters](#configuration-parameters). + +In this example, the final configuration of the `ml_inference` processor with the local model is as follows: + +```json +PUT /_ingest/pipeline/ml_inference_pipeline_local +{ + "description": "ingests reviews and generates embeddings", + "processors": [ + { + "ml_inference": { + "function_name": "text_embedding", + "full_response_path": true, + "model_id": "", + "model_config": { + "return_number": true, + "target_response": ["sentence_embedding"] + }, + "model_input": "{ \"text_docs\": ${input_map.text_docs}, \"return_number\": ${model_config.return_number}, \"target_response\": ${model_config.target_response} }", + "input_map": [ + { + "text_docs": "book.*.chunk.text.*.context" + } + ], + "output_map": [ + { + "book.*.chunk.text.*.context_embedding": "$.inference_results.*.output.*.data" + } + ], + "ignore_missing": true, + "ignore_failure": true + } + } + ] +} +``` +{% include copy-curl.html %} -## Limitation +**Step 2 (Optional): Test the pipeline** -The `ml_inference` processor currently supports only remote models connected through a connector. Local models uploaded to an OpenSearch cluster are not yet supported. Check the [OpenSearch Project Roadmap](https://github.com/orgs/opensearch-project/projects/1) for updates on upcoming features. +To test the pipeline, run the following query: +```json +POST _ingest/pipeline/ml_inference_pipeline/_simulate +{ + "docs": [ + { + "_index": "my_books", + "_id": "1", + "_source": { + "book": [ + { + "chunk": { + "text": [ + { + "chapter": "first chapter", + "context": "this is the first part" + }, + { + "chapter": "first chapter", + "context": "this is the second part" + } + ] + } + }, + { + "chunk": { + "text": [ + { + "chapter": "second chapter", + "context": "this is the third part" + }, + { + "chapter": "second chapter", + "context": "this is the fourth part" + } + ] + } + } + ] + } + } + ] +} +``` +{% include copy-curl.html %} + +#### Response + +The response confirms that the processor has generated text embeddings in the `context_embedding` field. The document now contains both the `context` and `context_embedding` fields at the same path: + +```json +{ + "docs" : [ + { + "doc" : { + "_index": "my_books", + "_id": "1", + "_source": { + "book": [ + { + "chunk": { + "text": [ + { + "chapter": "first chapter", + "context": "this is the first part", + "context_embedding": [ + 0.15756914, + 0.05150984, + 0.25225413, + 0.4941875, + ... + ] + }, + { + "chapter": "first chapter", + "context": "this is the second part", + "context_embedding": [ + 0.10526893, + 0.026559234, + 0.28763372, + 0.4653795, + ... + ] + } + ] + } + }, + { + "chunk": { + "text": [ + { + "chapter": "second chapter", + "context": "this is the third part", + "context_embedding": [ + 0.017304314, + -0.021530833, + 0.050184276, + 0.08962978, + ... + ] + }, + { + "chapter": "second chapter", + "context": "this is the fourth part", + "context_embedding": [ + 0.37742054, + 0.046911318, + 1.2053889, + 0.04663613, + ... + ] + } + ] + } + } + ] + } + } + } + ] +} +``` + +Once you have created an ingest pipeline, you need to create an index for ingestion and ingest documents into the index. +{: .note} \ No newline at end of file diff --git a/_ingest-pipelines/processors/pipeline.md b/_ingest-pipelines/processors/pipeline.md new file mode 100644 index 0000000000..5c1c6306d1 --- /dev/null +++ b/_ingest-pipelines/processors/pipeline.md @@ -0,0 +1,183 @@ +--- +layout: default +title: Pipeline +parent: Ingest processors +nav_order: 220 +--- + +# Pipeline processor + +The `pipeline` processor allows a pipeline to reference and include another predefined pipeline. This can be useful when you have a set of common processors that need to be shared across multiple pipelines. Instead of redefining those common processors in each pipeline, you can create a separate base pipeline containing the shared processors and then reference that base pipeline from other pipelines using the pipeline processor. + +The following is the syntax for the `pipeline` processor: + +```json +{ + "pipeline": { + "name": "general-pipeline" + } +} +``` +{% include copy-curl.html %} + +## Configuration parameters + +The following table lists the required and optional parameters for the `pipeline` processor. + +Parameter | Required/Optional | Description | +|-----------|-----------|-----------| +`name` | Required | The name of the pipeline to execute. +`description` | Optional | A description of the processor's purpose or configuration. +`if` | Optional | Specifies to conditionally execute the processor. +`ignore_failure` | Optional | Specifies to ignore processor failures. See [Handling pipeline failures]({{site.url}}{{site.baseurl}}/ingest-pipelines/pipeline-failures/). +`on_failure` | Optional | Specifies to handle processor failures. See [Handling pipeline failures]({{site.url}}{{site.baseurl}}/ingest-pipelines/pipeline-failures/). +`tag` | Optional | An identifier for the processor. Useful for debugging and metrics. + +## Using the processor + +Follow these steps to use the processor in a pipeline. + +### Step 1: Create a pipeline + +The following query creates a general pipeline named `general-pipeline` and then creates a new pipeline named `outer-pipeline`, which references the `general-pipeline`: + +```json +PUT _ingest/pipeline/general_pipeline +{ + "description": "a general pipeline", + "processors": [ + { + "uppercase": { + "field": "protocol" + }, + "remove": { + "field": "name" + } + } + ] +} +``` +{% include copy-curl.html %} + +```json +PUT _ingest/pipeline/outer-pipeline +{ + "description": "an outer pipeline referencing the general pipeline", + "processors": [ + { + "pipeline": { + "name": "general-pipeline" + } + } + ] +} +``` +{% include copy-curl.html %} + +### Step 2 (Optional): Test the pipeline + +It is recommended that you test your pipeline before you ingest documents. +{: .tip} + +To test the pipeline, run the following query: + +```json +POST _ingest/pipeline/outer-pipeline/_simulate +{ + "docs": [ + { + "_source": { + "protocol": "https", + "name":"test" + } + } + ] +} +``` +{% include copy-curl.html %} + +#### Response + +The following example response confirms that the pipeline is working as expected: + +```json +{ + "docs": [ + { + "doc": { + "_index": "_index", + "_id": "_id", + "_source": { + "protocol": "HTTPS" + }, + "_ingest": { + "timestamp": "2024-05-24T02:43:43.700735801Z" + } + } + } + ] +} +``` +{% include copy-curl.html %} + +### Step 3: Ingest a document + +The following query ingests a document into an index named `testindex1`: + +```json +POST testindex1/_doc/1?pipeline=outer-pipeline +{ + "protocol": "https", + "name": "test" +} +``` +{% include copy-curl.html %} + +#### Response + +The request indexes the document with the `protocol` field converted to uppercase and the field name removed from the index `testindex1`, as shown in the following response: + +```json +{ + "_index": "testindex1", + "_id": "1", + "_version": 2, + "result": "created", + "_shards": { + "total": 2, + "successful": 2, + "failed": 0 + }, + "_seq_no": 1, + "_primary_term": 1 +} +``` +{% include copy-curl.html %} + +### Step 4 (Optional): Retrieve the document + +To retrieve the document, run the following query: + +```json +GET testindex1/_doc/1 +``` +{% include copy-curl.html %} + +#### Response + +The response shows the document with the `protocol` field converted to uppercase and the field name removed: + +```json +{ + "_index": "testindex1", + "_id": "1", + "_version": 2, + "_seq_no": 1, + "_primary_term": 1, + "found": true, + "_source": { + "protocol": "HTTPS" + } +} +``` + diff --git a/_ingest-pipelines/processors/script.md b/_ingest-pipelines/processors/script.md new file mode 100644 index 0000000000..ae8e0bd9c6 --- /dev/null +++ b/_ingest-pipelines/processors/script.md @@ -0,0 +1,155 @@ +--- +layout: default +title: Script +parent: Ingest processors +nav_order: 230 +--- + +# Script processor + +The `script` processor executes inline and stored scripts that can modify or transform data in an OpenSearch document during the ingestion process. The processor uses script caching for improved performance because scripts may be recompiled per document. Refer to [Script APIs](https://opensearch.org/docs/latest/api-reference/script-apis/index/) for information about working with scripts in OpenSearch. + +The following is the syntax for the `script` processor: + +```json +{ + "processor": { + "script": { + "source": "", + "lang": "", + "params": { + "": "" + } + } + } +} +``` +{% include copy-curl.html %} + +## Configuration parameters + +The following table lists the required and optional parameters for the `script` processor. + +| Parameter | Required/Optional | Description | +|---|---|---| +`source` | Optional | The Painless script to be executed. Either `id` or `source` must be specified---but not both. If `source` is specified, then the script is executed using the provided source code. +`id` | Optional | The ID of a stored script previously created using the [Create Stored Script API]({{site.url}}{{site.baseurl}}/api-reference/script-apis/create-stored-script/). Either `id` or `source` must be specified, but not both. If `id` is specified, then the script source is retrieved from the stored script with the specified ID. +`lang` | Optional | The programming language of the script. Default is `painless`. +`params` | Optional | The parameters that can be passed to the script. +`description` | Optional | A description of the processor's purpose or configuration. +`if` | Optional | Specifies to conditionally execute the processor. +`ignore_failure` | Optional | Specifies to ignore processor failures. See [Handling pipeline failures]({{site.url}}{{site.baseurl}}/ingest-pipelines/pipeline-failures/). +`on_failure` | Optional | Specifies a list of processors to run if the processor fails during execution. These processors are executed in the order they are specified. See [Handling pipeline failures]({{site.url}}{{site.baseurl}}/ingest-pipelines/pipeline-failures/). +`tag` | Optional | An identifier tag for the processor. Useful for debugging in order to distinguish between processors of the same type. + +## Using the processor + +Follow these steps to use the processor in a pipeline. + +### Step 1: Create a pipeline + +The following query creates a pipeline named `my-script-pipeline` that uses the `script` processor to convert the `message` field to uppercase: + +```json +PUT _ingest/pipeline/my-script-pipeline +{ + "description": "Example pipeline using the ScriptProcessor", + "processors": [ + { + "script": { + "source": "ctx.message = ctx.message.toUpperCase()", + "lang": "painless", + "description": "Convert message field to uppercase" + } + } + ] +} +``` +{% include copy-curl.html %} + +### Step 2 (Optional): Test the pipeline + +It is recommended that you test your pipeline before you ingest documents. +{: .tip} + +To test the pipeline, run the following query: + +```json +POST _ingest/pipeline/my-script-pipeline/_simulate +{ + "docs": [ + { + "_source": { + "message": "hello, world!" + } + } + ] +} +``` +{% include copy-curl.html %} + +#### Response + +The following example response confirms that the pipeline is working as expected: + +```json +{ + "docs": [ + { + "doc": { + "_index": "_index", + "_id": "_id", + "_source": { + "message": "HELLO, WORLD!" + }, + "_ingest": { + "timestamp": "2024-05-30T16:24:23.30265405Z" + } + } + } + ] +} +``` +{% include copy-curl.html %} + +### Step 3: Ingest a document + +The following query ingests a document into an index named `testindex1`: + +```json +POST testindex1/_doc?pipeline=my-script-pipeline +{ + "message": "hello, world!" +} +``` +{% include copy-curl.html %} + +#### Response + +The response confirms that the document has been indexed into `testindex1` and has indexed all documents with the `message` field converted to uppercase: + +```json +{ + "_index": "testindex1", + "_id": "1", + "_version": 1, + "result": "created", + "_shards": { + "total": 2, + "successful": 1, + "failed": 0 + }, + "_seq_no": 6, + "_primary_term": 2 +} +``` +{% include copy-curl.html %} + +### Step 4 (Optional): Retrieve the document + +To retrieve the document, run the following query: + +```json +GET testindex1/_doc/1 +``` +{% include copy-curl.html %} diff --git a/_ingest-pipelines/processors/set.md b/_ingest-pipelines/processors/set.md new file mode 100644 index 0000000000..1abf9775b9 --- /dev/null +++ b/_ingest-pipelines/processors/set.md @@ -0,0 +1,155 @@ +--- +layout: default +title: Set +parent: Ingest processors +nav_order: 240 +--- + +# Set processor + +The `set` processor adds or updates fields in a document. It sets one field and associates it with the specified value. If the field already exists, then its value is replaced with the provided one unless the `override` parameter is set to `false`. When `override` is `false` and the specified field exists, the value of the field remains unchanged. + +The following is the syntax for the `set` processor: + +```json +{ + "description": "...", + "processors": [ + { + "set": { + "field": "new_field", + "value": "some_value" + } + } + ] +} +``` +{% include copy-curl.html %} + +## Configuration parameters + +The following table lists the required and optional parameters for the `set` processor. + +Parameter | Required/Optional | Description | +|-----------|-----------|-----------| +`field` | Required | The name of the field to be set or updated. Supports [template snippets]({{site.url}}{{site.baseurl}}/ingest-pipelines/create-ingest/#template-snippets). +`value` | Required | The value assigned to the field. Supports [template snippets]({{site.url}}{{site.baseurl}}/ingest-pipelines/create-ingest/#template-snippets). +`override` | Optional | A Boolean flag that determines whether the processor should override the existing value of the field. +`ignore_empty_value` | Optional | A Boolean flag that determines whether the processor should ignore `null` values or empty strings. Default is `false`. +`description` | Optional | A description of the processor's purpose or configuration. +`if` | Optional | Specifies to conditionally execute the processor. +`ignore_failure` | Optional | Specifies to ignore processor failures. See [Handling pipeline failures]({{site.url}}{{site.baseurl}}/ingest-pipelines/pipeline-failures/). +`on_failure` | Optional | Specifies a list of processors to run if the processor fails during execution. These processors are executed in the order they are specified. +`tag` | Optional | An identifier tag for the processor. Useful for debugging in order to distinguish between processors of the same type. + +## Using the processor + +Follow these steps to use the processor in a pipeline. + +### Step 1: Create a pipeline + +The following query creates a pipeline named `set-pipeline` that uses the `set` processor to add a new field `new_field` with the value `some_value` to the document: + +```json +PUT _ingest/pipeline/set-pipeline +{ + "description": "Adds a new field 'new_field' with the value 'some_value'", + "processors": [ + { + "set": { + "field": "new_field", + "value": "some_value" + } + } + ] +} +``` +{% include copy-curl.html %} + +### Step 2 (Optional): Test the pipeline + +It is recommended that you test your pipeline before you ingest documents. +{: .tip} + +To test the pipeline, run the following query: + +```json +POST _ingest/pipeline/set-pipeline/_simulate +{ + "docs": [ + { + "_source": { + "existing_field": "value" + } + } + ] +} +``` +{% include copy-curl.html %} + +#### Response + +The following example response confirms that the pipeline is working as expected: + +```json +{ + "docs": [ + { + "doc": { + "_index": "_index", + "_id": "_id", + "_source": { + "existing_field": "value", + "new_field": "some_value" + }, + "_ingest": { + "timestamp": "2024-05-30T21:56:15.066180712Z" + } + } + } + ] +} +``` +{% include copy-curl.html %} + +### Step 3: Ingest a document + +The following query ingests a document into an index named `testindex1`: + +```json +POST testindex1/_doc?pipeline=set-pipeline +{ + "existing_field": "value" +} +``` +{% include copy-curl.html %} + +#### Response + +The request indexes the document into the index `testindex1` and then indexes all documents with the `new_field` set to `some_value`, as shown in the following response: + +```json +{ + "_index": "testindex1", + "_id": "1", + "_version": 1, + "result": "created", + "_shards": { + "total": 2, + "successful": 1, + "failed": 0 + }, + "_seq_no": 0, + "_primary_term": 1 +} +``` +{% include copy-curl.html %} + +### Step 4 (Optional): Retrieve the document + +To retrieve the document, run the following query: + +```json +GET testindex1/_doc/1 +``` +{% include copy-curl.html %} diff --git a/_ingest-pipelines/processors/sort.md b/_ingest-pipelines/processors/sort.md new file mode 100644 index 0000000000..7f1377bc32 --- /dev/null +++ b/_ingest-pipelines/processors/sort.md @@ -0,0 +1,176 @@ +--- +layout: default +title: Sort +parent: Ingest processors +nav_order: 250 +--- + +# Sort processor + +The `sort` processor sorts an array of items in either ascending or descending order. Numeric arrays are sorted numerically, while string or mixed arrays (strings and numbers) are sorted lexicographically. The processor throws an error if the input is not an array. + +The following is the syntax for the `sort` processor: + +```json +{ + "description": "Sort an array of items", + "processors": [ + { + "sort": { + "field": "my_array_field", + "order": "desc" + } + } + ] +} +``` +{% include copy-curl.html %} + +## Configuration parameters + +The following table lists the required and optional parameters for the `sort` processor. + +| Parameter | Required/Optional | Description | +|---|---|---| +`field` | Required | The field to be sorted. Must be an array. +`order` | Optional | The sort order to apply. Accepts `asc` for ascending or `desc` for descending. Default is `asc`. +`target_field` | Optional | The name of the field in which the sorted array is stored. If not specified, then the sorted array is stored in the same field as the original array (the `field` variable). +`description` | Optional | A description of the processor's purpose or configuration. +`if` | Optional | Specifies to conditionally execute the processor. +`ignore_failure` | Optional | Specifies to ignore processor failures. See [Handling pipeline failures]({{site.url}}{{site.baseurl}}/ingest-pipelines/pipeline-failures/). +`on_failure` | Optional | Specifies a list of processors to run if the processor fails during execution. These processors are executed in the order they are specified. +`tag` | Optional | An identifier tag for the processor. Useful for debugging in order to distinguish between processors of the same type. + +## Using the processor + +Follow these steps to use the processor in a pipeline. + +### Step 1: Create a pipeline + +The following query creates a pipeline named `sort-pipeline` that uses the `sort` processor to sort the `my_field` in descending order and store the sorted values in the `sorted_field`: + +```json +PUT _ingest/pipeline/sort-pipeline +{ + "description": "Sort an array of items in descending order", + "processors": [ + { + "sort": { + "field": "my_array_field", + "order": "desc", + "target_field": "sorted_array" + } + } + ] +} +``` +{% include copy-curl.html %} + +### Step 2 (Optional): Test the pipeline + +It is recommended that you test your pipeline before you ingest documents. +{: .tip} + +To test the pipeline, run the following query: + +```json +POST _ingest/pipeline/sort-pipeline/_simulate +{ + "docs": [ + { + "_source": { + "my_array_field": [3, 1, 4, 1, 5, 9, 2, 6, 5] + } + } + ] +} +``` +{% include copy-curl.html %} + +#### Response + +The following example response confirms that the pipeline is working as expected: + +```json +{ + "docs": [ + { + "doc": { + "_index": "_index", + "_id": "_id", + "_source": { + "sorted_array": [ + 9, + 6, + 5, + 5, + 4, + 3, + 2, + 1, + 1 + ], + "my_array_field": [ + 3, + 1, + 4, + 1, + 5, + 9, + 2, + 6, + 5 + ] + }, + "_ingest": { + "timestamp": "2024-05-30T22:10:13.405692128Z" + } + } + } + ] +} +``` +{% include copy-curl.html %} + +### Step 3: Ingest a document + +The following query ingests a document into an index named `testindex1`: + +```json +POST testindex1/_doc?pipeline=sort-pipeline +{ + "my_array_field": [3, 1, 4, 1, 5, 9, 2, 6, 5] +} +``` +{% include copy-curl.html %} + +#### Response + +The request indexes the document into the index `testindex1` and then indexes all documents with the `my_array_field` sorted in descending order, as shown in the following response: + +```json +{ + "_index": "testindex1", + "_id": "no-Py48BwFahnwl9KZzf", + "_version": 1, + "result": "created", + "_shards": { + "total": 2, + "successful": 1, + "failed": 0 + }, + "_seq_no": 9, + "_primary_term": 2 +} +``` +{% include copy-curl.html %} + +### Step 4 (Optional): Retrieve the document + +To retrieve the document, run the following query: + +```json +GET testindex1/_doc/no-Py48BwFahnwl9KZzf +``` +{% include copy-curl.html %} + diff --git a/_ingest-pipelines/processors/split.md b/_ingest-pipelines/processors/split.md new file mode 100644 index 0000000000..2052c3def1 --- /dev/null +++ b/_ingest-pipelines/processors/split.md @@ -0,0 +1,180 @@ +--- +layout: default +title: Split +parent: Ingest processors +nav_order: 270 +--- + +# Split processor + +The `split` processor is used to split a string field into an array of substrings based on a specified delimiter. + +The following is the syntax for the `split` processor: + +```json +{ + "split": { + "field": "field_to_split", + "separator": "", + "target_field": "split_field" + } +} +``` +{% include copy-curl.html %} + +## Configuration parameters + +The following table lists the required and optional parameters for the `split` processor. + +Parameter | Required/Optional | Description | +|-----------|-----------|-----------| +`field` | Required | The field containing the string to be split. +`separator` | Required | The delimiter used to split the string. This can be a regular expression pattern. +`preserve_field` | Optional | If set to `true`, preserves empty trailing fields (for example, `''`) in the resulting array. If set to `false`, empty trailing fields are removed from the resulting array. Default is `false`. +`target_field` | Optional | The field where the array of substrings is stored. If not specified, then the field is updated in-place. +`ignore_missing` | Optional | Specifies whether the processor should ignore documents that do not contain the specified +field. If set to `true`, then the processor ignores missing values in the field and leaves the `target_field` unchanged. Default is `false`. +`description` | Optional | A brief description of the processor. +`if` | Optional | A condition for running the processor. +`ignore_failure` | Optional | Specifies whether the processor continues execution even if it encounters an error. If set to `true`, then failures are ignored. Default is `false`. +`on_failure` | Optional | A list of processors to run if the processor fails. +`tag` | Optional | An identifier tag for the processor. Useful for debugging in order to distinguish between processors of the same type. + +## Using the processor + +Follow these steps to use the processor in a pipeline. + +### Step 1: Create a pipeline + +The following query creates a pipeline named `split_pipeline` that uses the `split` processor to split the `log_message` field on the comma character and store the resulting array in the `log_parts` field: + +```json +PUT _ingest/pipeline/split_pipeline +{ + "description": "Split log messages by comma", + "processors": [ + { + "split": { + "field": "log_message", + "separator": ",", + "target_field": "log_parts" + } + } + ] +} +``` +{% include copy-curl.html %} + +### Step 2 (Optional): Test the pipeline + +It is recommended that you test your pipeline before you ingest documents. +{: .tip} + +To test the pipeline, run the following query: + +```json +POST _ingest/pipeline/split_pipeline/_simulate +{ + "docs": [ + { + "_source": { + "log_message": "error,warning,info" + } + } + ] +} +``` +{% include copy-curl.html %} + +#### Response + +The following example response confirms that the pipeline is working as expected: + +```json +{ + "docs": [ + { + "doc": { + "_index": "_index", + "_id": "_id", + "_source": { + "log_message": "error,warning,info", + "log_parts": [ + "error", + "warning", + "info" + ] + }, + "_ingest": { + "timestamp": "2024-04-26T22:29:23.207849376Z" + } + } + } + ] +} +``` +{% include copy-curl.html %} + +### Step 3: Ingest a document + +The following query ingests a document into an index named `testindex1`: + +```json +PUT testindex1/_doc/1?pipeline=split_pipeline +{ + "log_message": "error,warning,info" +} +``` +{% include copy-curl.html %} + +#### Response + +The request indexes the document into the index `testindex1` and splits the `log_message` field on the comma delimiter before indexing, as shown in the following response: + +```json +{ + "_index": "testindex1", + "_id": "1", + "_version": 70, + "result": "updated", + "_shards": { + "total": 2, + "successful": 1, + "failed": 0 + }, + "_seq_no": 72, + "_primary_term": 47 +} +``` + +### Step 4 (Optional): Retrieve the document + +To retrieve the document, run the following query: + +```json +GET testindex1/_doc/1 +``` +{% include copy-curl.html %} + +#### Response + +The response shows the `log_message` field as an array of values split on the comma delimiter: + +```json +{ + "_index": "testindex1", + "_id": "1", + "_version": 70, + "_seq_no": 72, + "_primary_term": 47, + "found": true, + "_source": { + "log_message": "error,warning,info", + "log_parts": [ + "error", + "warning", + "info" + ] + } +} +``` diff --git a/_ingest-pipelines/processors/trim.md b/_ingest-pipelines/processors/trim.md new file mode 100644 index 0000000000..9c1999aeb2 --- /dev/null +++ b/_ingest-pipelines/processors/trim.md @@ -0,0 +1,165 @@ +--- +layout: default +title: Trim +parent: Ingest processors +nav_order: 300 +--- + +# Trim processor + +The `trim` processor is used to remove leading and trailing white space characters from a specified field. + +The following is the syntax for the `trim` processor: + +```json +{ + "trim": { + "field": "field_to_trim", + "target_field": "trimmed_field" + } +} +``` +{% include copy-curl.html %} + +## Configuration parameters + +The following table lists the required and optional parameters for the `trim` processor. + +Parameter | Required/Optional | Description | +|-----------|-----------|-----------| +`field` | Required | The field containing the text to be trimmed. +`target_field` | Required | The field in which the trimmed text is stored. If not specified, then the field is updated in-place. +`ignore_missing` | Optional | Specifies whether the processor should ignore documents that do not contain the specified +field. If set to `true`, then the processor ignores missing values in the field and leaves the `target_field` unchanged. Default is `false`. +`description` | Optional | A brief description of the processor. +`if` | Optional | A condition for running the processor. +`ignore_failure` | Optional | Specifies whether the processor continues execution even if it encounters an error. If set to `true`, then failures are ignored. Default is `false`. +`on_failure` | Optional | A list of processors to run if the processor fails. +`tag` | Optional | An identifier tag for the processor. Useful for debugging in order to distinguish between processors of the same type. + +## Using the processor + +Follow these steps to use the processor in a pipeline. + +### Step 1: Create a pipeline + +The following query creates a pipeline named `trim_pipeline` that uses the `trim` processor to remove leading and trailing white space from the `raw_text` field and store the trimmed text in the `trimmed_text` field: + +```json +PUT _ingest/pipeline/trim_pipeline +{ + "description": "Trim leading and trailing white space", + "processors": [ + { + "trim": { + "field": "raw_text", + "target_field": "trimmed_text" + } + } + ] +} +``` +{% include copy-curl.html %} + +### Step 2 (Optional): Test the pipeline + +It is recommended that you test your pipeline before you ingest documents. +{: .tip} + +To test the pipeline, run the following query: + +```json +POST _ingest/pipeline/trim_pipeline/_simulate +{ + "docs": [ + { + "_source": { + "raw_text": " Hello, world! " + } + } + ] +} +``` +{% include copy-curl.html %} + +#### Response + +The following example response confirms that the pipeline is working as expected: + +```json +{ + "docs": [ + { + "doc": { + "_index": "_index", + "_id": "_id", + "_source": { + "raw_text": " Hello, world! ", + "trimmed_text": "Hello, world!" + }, + "_ingest": { + "timestamp": "2024-04-26T20:58:17.418006805Z" + } + } + } + ] +} +``` + +### Step 3: Ingest a document + +The following query ingests a document into an index named `testindex1`: + +```json +PUT testindex1/_doc/1?pipeline=trim_pipeline +{ + "message": " This is a test document. " +} +``` +{% include copy-curl.html %} + +#### Response + +The request indexes the document into the index `testindex1` and indexes all documents with the `raw_text` field, which is processed by the `trim_pipeline`, to populate the `trimmed_text` field, as shown in the following response: + +```json + "_index": "testindex1", + "_id": "1", + "_version": 68, + "result": "updated", + "_shards": { + "total": 2, + "successful": 1, + "failed": 0 + }, + "_seq_no": 70, + "_primary_term": 47 +} +``` +{% include copy-curl.html %} + +### Step 4 (Optional): Retrieve the document + +To retrieve the document, run the following query: + +```json +GET testindex1/_doc/1 +``` +{% include copy-curl.html %} + +The response includes the `trimmed_text` field with the leading and trailing white space removed: + +```json +{ + "_index": "testindex1", + "_id": "1", + "_version": 69, + "_seq_no": 71, + "_primary_term": 47, + "found": true, + "_source": { + "raw_text": " This is a test document. ", + "trimmed_text": "This is a test document." + } +} +``` diff --git a/_install-and-configure/configuring-opensearch/index-settings.md b/_install-and-configure/configuring-opensearch/index-settings.md index 1620a0462c..34b1829b78 100644 --- a/_install-and-configure/configuring-opensearch/index-settings.md +++ b/_install-and-configure/configuring-opensearch/index-settings.md @@ -15,7 +15,22 @@ To learn more about static and dynamic settings, see [Configuring OpenSearch]({{ ## Cluster-level index settings -OpenSearch supports the following cluster-level index settings. All settings in this list are dynamic: +There are two types of cluster settings: + +- [Static cluster-level index settings](#static-cluster-level-index-settings) are settings that you cannot update while the cluster is running. To update a static setting, you must stop the cluster, update the setting, and then restart the cluster. +- [Dynamic cluster-level index settings](#dynamic-cluster-level-index-settings) are settings that you can update at any time. + +### Static cluster-level index settings + +OpenSearch supports the following static cluster-level index settings: + +- `indices.cache.cleanup_interval` (Time unit): Schedules a recurring background task that cleans up expired entries from the cache at the specified interval. Default is `1m` (1 minute). For more information, see [Index request cache]({{site.url}}{{site.baseurl}}/search-plugins/caching/request-cache/). + +- `indices.requests.cache.size` (String): The cache size as a percentage of the heap size (for example, to use 1% of the heap, specify `1%`). Default is `1%`. For more information, see [Index request cache]({{site.url}}{{site.baseurl}}/search-plugins/caching/request-cache/). + +### Dynamic cluster-level index settings + +OpenSearch supports the following dynamic cluster-level index settings: - `action.auto_create_index` (Boolean): Automatically creates an index if the index doesn't already exist. Also applies any index templates that are configured. Default is `true`. @@ -54,6 +69,7 @@ OpenSearch supports the following cluster-level index settings. All settings in - `cluster.remote_store.index.segment_metadata.retention.max_count` (Integer): Controls the minimum number of metadata files to keep in the segment repository on a remote store. A value below `1` disables the deletion of stale segment metadata files. Default is `10`. +- `cluster.remote_store.segment.transfer_timeout` (Time unit): Controls the maximum amount of time to wait for all new segments to update after refresh to the remote store. If the upload does not complete within a specified amount of time, it throws a `SegmentUploadFailedException` error. Default is `30m`. It has a minimum constraint of `10m`. ## Index-level index settings @@ -104,9 +120,6 @@ For `zstd`, `zstd_no_dict`, `qat_lz4`, and `qat_deflate`, you can specify the co - `index.codec.qatmode` (String): The hardware acceleration mode used for the `qat_lz4` and `qat_deflate` compression codecs. Valid values are `auto` and `hardware`. For more information, see [Index codec settings]({{site.url}}{{site.baseurl}}/im-plugin/index-codecs/). Optional. Default is `auto`. - - - - `index.routing_partition_size` (Integer): The number of shards a custom routing value can go to. Routing helps an imbalanced cluster by relocating values to a subset of shards rather than a single shard. To enable routing, set this value to greater than 1 but less than `index.number_of_shards`. Default is 1. - `index.soft_deletes.retention_lease.period` (Time unit): The maximum amount of time to retain a shard's history of operations. Default is `12h`. @@ -125,6 +138,8 @@ For `zstd`, `zstd_no_dict`, `qat_lz4`, and `qat_deflate`, you can specify the co - `index.check_pending_flush.enabled` (Boolean): This setting controls the Apache Lucene `checkPendingFlushOnUpdate` index writer setting, which specifies whether an indexing thread should check for pending flushes on an update in order to flush indexing buffers to disk. Default is `true`. +- `index.use_compound_file` (Boolean): This setting controls the Apache Lucene `useCompoundFile` index writer settings, which specifies whether newly written segment files will be packed into a compound file. Default is `true`. + ### Updating a static index setting You can update a static index setting only on a closed index. The following example demonstrates updating the index codec setting. @@ -200,6 +215,8 @@ OpenSearch supports the following dynamic index-level index settings: - `index.query.max_nested_depth` (Integer): The maximum number of nesting levels for `nested` queries. Default is `Integer.MAX_VALUE`. Minimum is 1 (single `nested` query). +- `index.requests.cache.enable` (Boolean): Enables or disables the index request cache. Default is `true`. For more information, see [Index request cache]({{site.url}}{{site.baseurl}}/search-plugins/caching/request-cache/). + - `index.routing.allocation.enable` (String): Specifies options for the index’s shard allocation. Available options are `all` (allow allocation for all shards), `primaries` (allow allocation only for primary shards), `new_primaries` (allow allocation only for new primary shards), and `none` (do not allow allocation). Default is `all`. - `index.routing.rebalance.enable` (String): Enables shard rebalancing for the index. Available options are `all` (allow rebalancing for all shards), `primaries` (allow rebalancing only for primary shards), `replicas` (allow rebalancing only for replicas), and `none` (do not allow rebalancing). Default is `all`. diff --git a/_install-and-configure/configuring-opensearch/search-settings.md b/_install-and-configure/configuring-opensearch/search-settings.md index f769516b33..c3c4337d01 100644 --- a/_install-and-configure/configuring-opensearch/search-settings.md +++ b/_install-and-configure/configuring-opensearch/search-settings.md @@ -35,7 +35,9 @@ OpenSearch supports the following search settings: - `search.highlight.term_vector_multi_value` (Static, Boolean): Specifies to highlight snippets across values of a multi-valued field. Default is `true`. -- `search.max_aggregation_rewrite_filters` (Dynamic, integer): Determines the maximum number of rewrite filters allowed during aggregation. Set this value to `0` to disable the filter rewrite optimization for aggregations. +- `search.max_aggregation_rewrite_filters` (Dynamic, integer): Determines the maximum number of rewrite filters allowed during aggregation. Set this value to `0` to disable the filter rewrite optimization for aggregations. This is an experimental feature and may change or be removed in future versions. + +- `search.dynamic_pruning.cardinality_aggregation.max_allowed_cardinality` (Dynamic, integer): Determines the threshold for applying dynamic pruning in cardinality aggregation. If a field’s cardinality exceeds this threshold, the aggregation reverts to the default method. This is an experimental feature and may change or be removed in future versions. ## Point in Time settings diff --git a/_install-and-configure/configuring-opensearch/security-settings.md b/_install-and-configure/configuring-opensearch/security-settings.md index 3ea3e3a6ab..244d601449 100644 --- a/_install-and-configure/configuring-opensearch/security-settings.md +++ b/_install-and-configure/configuring-opensearch/security-settings.md @@ -33,8 +33,12 @@ The Security plugin supports the following common settings: - `plugins.security.compliance.salt` (Static): The salt to use when generating the hash value for field masking. Must be at least 32 characters. Only ASCII characters are allowed. Optional. +- `plugins.security.compliance.immutable_indices` (Static): Documents in indexes that are marked as immutable follow the write-once, read-many paradigm. Documents created in these indexes cannot be changed and are therefore immutable. + - `config.dynamic.http.anonymous_auth_enabled` (Static): Enables anonymous authentication. This will cause all HTTP authenticators to not challenge. Default is `false`. +- `http.detailed_errors.enabled` (Static): Enables a detailed error message for REST calls performed against the OpenSearch cluster. If set to `true`, provides the `root_cause` together with the error code. Default is `true`. + ## REST management API settings The Security plugin supports the following REST management API settings: diff --git a/_install-and-configure/install-dashboards/tls.md b/_install-and-configure/install-dashboards/tls.md index ba3da7998c..29f35fa921 100644 --- a/_install-and-configure/install-dashboards/tls.md +++ b/_install-and-configure/install-dashboards/tls.md @@ -40,6 +40,7 @@ Setting | Description The following `opensearch_dashboards.yml` configuration shows OpenSearch and OpenSearch Dashboards running on the same machine with the demo configuration: ```yml +server.host: '0.0.0.0' server.ssl.enabled: true server.ssl.certificate: /usr/share/opensearch-dashboards/config/client-cert.pem server.ssl.key: /usr/share/opensearch-dashboards/config/client-cert-key.pem diff --git a/_install-and-configure/plugins.md b/_install-and-configure/plugins.md index 6b0b28769e..d4fc35507f 100644 --- a/_install-and-configure/plugins.md +++ b/_install-and-configure/plugins.md @@ -176,7 +176,7 @@ bin/opensearch-plugin install :: ``` #### Example -```bash +```console $ sudo ./opensearch-plugin install org.opensearch.plugin:opensearch-anomaly-detection:2.2.0.0 -> Installing org.opensearch.plugin:opensearch-anomaly-detection:2.2.0.0 -> Downloading org.opensearch.plugin:opensearch-anomaly-detection:2.2.0.0 from maven central @@ -214,8 +214,8 @@ bin/opensearch-plugin install ... ``` #### Example -```bash -$ sudo $ ./opensearch-plugin install analysis-nori repository-s3 +```console +$ sudo ./opensearch-plugin install analysis-nori repository-s3 ``` ## Remove @@ -228,8 +228,8 @@ bin/opensearch-plugin remove ``` #### Example -```bash -$ sudo $ ./opensearch-plugin remove opensearch-anomaly-detection +```console +$ sudo ./opensearch-plugin remove opensearch-anomaly-detection -> removing [opensearch-anomaly-detection]... ``` @@ -285,6 +285,7 @@ The following plugins are bundled with all OpenSearch distributions except for m | Job Scheduler | [opensearch-job-scheduler](https://github.com/opensearch-project/job-scheduler) | 1.0.0 | | k-NN | [opensearch-knn](https://github.com/opensearch-project/k-NN) | 1.0.0 | | ML Commons | [opensearch-ml](https://github.com/opensearch-project/ml-commons) | 1.3.0 | +| Skills | [opensearch-skills](https://github.com/opensearch-project/skills) | 2.12.0 | | Neural Search | [neural-search](https://github.com/opensearch-project/neural-search) | 2.4.0 | | Observability | [opensearch-observability](https://github.com/opensearch-project/observability) | 1.2.0 | | Performance Analyzer2 | [opensearch-performance-analyzer](https://github.com/opensearch-project/performance-analyzer) | 1.0.0 | diff --git a/_install-and-configure/upgrade-opensearch/index.md b/_install-and-configure/upgrade-opensearch/index.md index 7535211a40..99265dc94e 100644 --- a/_install-and-configure/upgrade-opensearch/index.md +++ b/_install-and-configure/upgrade-opensearch/index.md @@ -137,6 +137,31 @@ td { OpenSearch Version Elasticsearch Version + + 9.10.0 + 2.14.0
2.13.0 + 8.13 + + + 9.9.2 + 2.12.0 + — + + + 9.7.0 + 2.11.1
2.9.0 + 8.9.0 + + + 9.6.0 + 2.8.0 + 8.8.0 + + + 9.5.0 + 2.7.0
2.6.0 + 8.7.0 + 9.4.2 2.5.0
2.4.1 diff --git a/_integrations/index.md b/_integrations/index.md index bb040f284f..644f3fccd2 100644 --- a/_integrations/index.md +++ b/_integrations/index.md @@ -1,6 +1,6 @@ --- layout: default -title: OpenSearch Integrations +title: Integrations in OpenSearch Dashboards nav_order: 1 has_children: false nav_exclude: true @@ -9,60 +9,102 @@ redirect_from: - /integrations/index/ --- -# OpenSearch Integrations +# Integrations in OpenSearch Dashboards Introduced 2.9 {: .label .label-purple } -OpenSearch Integrations is a straightforward starting point that OpenSearch and OpenSearch Dashboards users can use to visualize and understand log and metric data for a particular resource, such as NGINX. An _integration_ contains a bundle of metadata, data mappings, and visualizations that make it simple to monitor data from the Integrations resource. +The **Integrations** application in OpenSearch Dashboards provides a user-friendly platform for data visualization, querying, and projection of your resource data, such as flow logs. An _integration asset_, such NGINX or Amazon Virtual Private Cloud (VPC), contains a bundle of metadata, data mappings, and visualizations, streamlining the monitoring of resource data without redundant configuration steps. -The OpenSearch Project seeks your feedback on this feature. Let us know on the [OpenSearch forum](https://forum.opensearch.org/) how OpenSearch Integrations works for you or how it can be improved. -{: .label-yellow} +Available OpenSearch Dashboards integration assets are shown in the following image. -## Setting up OpenSearch Integrations +![Integrations assets available in OpenSearch Dashboards]({{site.url}}{{site.baseurl}}/images/dashboards/integrations-assets.png) -For the latest developer information, including sample code, articles, tutorials, and an API reference, see the following resources: +--- -- [Integrations repository](https://github.com/opensearch-project/observability/tree/e18cf354fd7720a6d5df6a6de5d53e51a9d43127/integrations) on GitHub -- [Integration Creation Guide](https://github.com/opensearch-project/dashboards-observability/wiki/Integration-Creation-Guide) -- [Integration Documentation Reference](https://github.com/opensearch-project/dashboards-observability/wiki/Integration-Documentation-Reference) -- [Observability plugin for OpenSearch Dashboards](https://github.com/opensearch-project/dashboards-observability/wiki) - -## Integrations schema +## Use cases + +**Integrations** considers established data schemas across multiple domains to give you seamless data mapping and integration for various use cases, such as e-commerce product search, observability monitoring (for example, trace and metrics analytics), and security monitoring and threat analysis. + +## OpenTelemetry protocol for observability + +A consistent telemetry data schema is crucial for effective observability, enabling data correlation and analysis across applications, services, and infrastructure components to provide a holistic view of system behavior and performance. + +OpenSearch adopted the [OpenTelemetry (OTel)](https://opentelemetry.io/) protocol as the foundation for its observability solution. OTel is a community-driven standard that defines a consistent schema and data collection approach for metrics, logs, and traces. It is widely supported by APIs, SDKs, and telemetry collectors, enabling features like auto-instrumentation for seamless observability integration. + +This shared schema allows cross-correlation and analysis across different data sources. To this end, OpenSearch derived the [Simple Schema for Observability](https://github.com/opensearch-project/opensearch-catalog/tree/main/docs/schema/observability), which encodes the OTel standard as OpenSearch mappings. OpenSearch also supports the [Piped Processing Language (PPL)](https://opensearch.org/docs/latest/search-plugins/sql/ppl/index/), which is designed for high-dimensionality querying in observability use cases. + +--- + +## Ingesting data + +Data ingested into OpenSearch must conform to the supported schemas for data integrations and their associated dashboards. Compatible data pipelines are required, such as the following: -The OpenSearch Integrations schema outlines how to capture, analyze, and visualize data. It includes the selection and configuration of monitoring tools, data collection methods, data storage and retention strategies, and visualization and alerting mechanisms. It follows the [OpenTelemetry Protocol convention](https://github.com/open-telemetry), with OpenSearch [Simple Schema for Observability](https://opensearch.org/docs/latest/observing-your-data/ssfo/) handling the translation from the OpenTelemetry (OTel) schema to the physical index mapping templates. +- [Data Prepper](https://github.com/opensearch-project/data-prepper) +- [OpenTelemetry Collector](https://github.com/open-telemetry/opentelemetry-collector) +- [Fluent Bit for OpenSearch](https://docs.fluentbit.io/manual/pipeline/outputs/opensearch) -Find detailed information about the schema, including schema examples, in the [OpenSearch Observability READ.me file](https://github.com/opensearch-project/opensearch-catalog/blob/main/docs/schema/observability/README.md) and on the [OpenSearch Observability wiki](https://github.com/opensearch-project/dashboards-observability/wiki/OpenSearch-Observability--Home#observability-schema). +These pipelines use the OTel schema (or a simple schema) to index signal documents into the correct index representing the observed resource signals. See [Naming Convention](https://github.com/opensearch-project/opensearch-catalog/blob/main/docs/schema/observability/Naming-convention.md) for index naming conventions. -## Get started +### Ingestion structure -Using the OpenSearch Dashboards interface, you can connect your data, applications, and processes so that you can centrally manage the services you use. All integrations are available in a single view, and OpenSearch Dashboards guides you there from the home page and main menu. +Each integration asset contains the following metadata and assets: -Learn how to do the following using the OpenSearch Dashboards interface: +* Name and description +* Source URL and license +* Schema specification, for example, mapping or component mapping +* Sample data for testing the feature +* Assets such as dashboards, index patterns, queries, or alerts -- Access integrations -- View integrations -- Add integrations +--- + +## Installing an integration asset + +Integration assets can be installed directly from the [default catalog](https://github.com/opensearch-project/opensearch-catalog/blob/main/docs/integrations/Release.md) shipped with every OpenSearch release. -The following image gives you a snapshot of the Integrations interface: +To install an asset, follow these steps: -![Get started with Integrations demo]({{site.url}}{{site.baseurl}}/images/integrations/nginx-integration.gif) +1. Go to **Integrations** > **Available** to view the available options. +2. Select a tool, such as **Nginx** or **Amazon VPC**. You can choose **Add** to add or configure a new data integration using a prepackaged integration asset. You can choose **Try it** to test or explore the integration before fully adding it. +3. On the **Available** page, select the **Categories** dropdown menu to filter the list of integrations. -### Access integrations +### Try it demo -To access integrations, open OpenSearch Dashboards and select **Integrations** from the **Management** menu. The interface displays installed and available integrations. +To try a prepackaged integration asset, follow these steps: -## View integrations +1. On the **Integrations** page, select **Nginx**. +2. Select the **Try it** button. The **Try it** option automatically creates a sample index template, adds sample data to the template, and then creates the integration based on that data. +3. Select an asset from the **Asset List**. Assets include dashboards, index patterns, and visualizations. +4. Preview the data visualizations and sample data details. An example is shown in the following image. -To view an integration, view the dashboard associated with the integration. If the integration doesn't have an associated dashboard, select the desired integration listed under the **Installed** window. View the integration details, such as assets and fields. + ![Integrations dashboard with visualizations]({{site.url}}{{site.baseurl}}/images/integrations/nginx-integration-dashboard.png) -## Add integrations +## Loading custom integration assets -If you have not installed any integrations, you'll be prompted to install them from the Integrations interface. Supported integrations are listed in the **Available** window. +To load a custom integration asset, follow these steps: + +1. Download an integration artifact from the [catalog repository](https://github.com/opensearch-project/opensearch-catalog/blob/main/docs/integrations/Release.md). +2. Go to **Dashboards Management** > **Saved objects**. +3. Select **Import** on the upper-right toolbar menu, navigate to the folder where you saved the integration artifact, and then choose the file (a file with an .ndjson extension). An example of this step is shown in the following image. + ![Import folder window]({{site.url}}{{site.baseurl}}/images/integrations/integration-import-file.png) +4. Select the saved object you uploaded to confirm that it was uploaded to **Saved objects**. An example of this step is shown in the following image. + ![List of integrations saved objects]({{site.url}}{{site.baseurl}}/images/integrations/select-uploaded-integration.png) + +--- -To add an integration, select the desired prepackaged assets. Currently, OpenSearch Integrations has two flows: Add or Try it. The following example uses the Try it flow: +## Developer resources -1. On the **Integrations** page, select **NginX Dashboard**. -2. Select the **Try it** button. _The Try it flow automatically creates a sample index template, adds sample data to the template, and then creates the integration based on that data._ -3. View the asset list and select a dashboard asset. -4. Preview the data visualizations and sample data details. +See the following developer resources for sample code, articles, tutorials, and an API reference: +- [OpenSearch Integrations repository](https://github.com/opensearch-project/opensearch-catalog) +- [OpenSearch Integrations reference documentation](https://github.com/opensearch-project/opensearch-catalog/tree/main/docs/integrations) +- [OpenSearch Observability Catalog](https://htmlpreview.github.io/?https://github.com/opensearch-project/opensearch-catalog/blob/main/integrations/observability/catalog.html) +- [OpenSearch Observability Catalog release page](https://github.com/opensearch-project/opensearch-catalog/blob/main/docs/integrations/Release.md) +- [Simple Schema for Observability](https://github.com/opensearch-project/opensearch-catalog/tree/main/docs/schema/observability) + +--- + +## Community contribution + +The OpenSearch Project seeks your feedback on this feature. Post on the [OpenSearch forum](https://forum.opensearch.org/) to let us know how **Integrations** works for you or how it can be improved. + +Contribute to the project by submitting an [integration request](https://github.com/opensearch-project/dashboards-observability/issues/new?assignees=&labels=integration%2C+untriaged&projects=&template=integration_request.md&title=%5BIntegration%5D). diff --git a/_layouts/default.html b/_layouts/default.html index 8ba6bd4703..d4d40d8cc4 100755 --- a/_layouts/default.html +++ b/_layouts/default.html @@ -165,9 +165,9 @@
{% if page.section == "opensearch" %} {% if site.doc_version == "supported" %} -

This is an earlier version of the OpenSearch documentation. For the latest version, see the current documentation. For information about OpenSearch version maintenance, see Release Schedule and Maintenance Policy.

+

You're viewing version {{site.opensearch_major_minor_version}} of the OpenSearch documentation. For the latest version, see the current documentation. For information about OpenSearch version maintenance, see Release Schedule and Maintenance Policy.

{% elsif site.doc_version == "unsupported" %} -

This version of the OpenSearch documentation is no longer maintained. For the latest version, see the current documentation. For information about OpenSearch version maintenance, see Release Schedule and Maintenance Policy.

+

You're viewing version {{site.opensearch_major_minor_version}} of the OpenSearch documentation. This version is no longer maintained. For the latest version, see the current documentation. For information about OpenSearch version maintenance, see Release Schedule and Maintenance Policy.

{% endif %} {% endif %} {% if site.heading_anchors != false %} diff --git a/_ml-commons-plugin/agents-tools/index.md b/_ml-commons-plugin/agents-tools/index.md index ba88edef2f..009906d4cf 100644 --- a/_ml-commons-plugin/agents-tools/index.md +++ b/_ml-commons-plugin/agents-tools/index.md @@ -18,7 +18,7 @@ An _agent_ is a coordinator that uses a large language model (LLM) to solve a pr - [_Flow agent_](#flow-agents): Runs tools sequentially, in the order specified in its configuration. The workflow of a flow agent is fixed. Useful for retrieval-augmented generation (RAG). - [_Conversational flow agent_](#conversational-flow-agents): Runs tools sequentially, in the order specified in its configuration. The workflow of a conversational flow agent is fixed. Stores conversation history so that users can ask follow-up questions. Useful for creating a chatbot. -- [_Conversational agent_](#conversational-agents): Reasons in order to provide a response based on the available knowledge, including the LLM knowledge base and a set of tools provided to the LLM. Stores conversation history so that users can ask follow-up questions. The workflow of a conversational agent is variable, based on follow-up questions. For specific questions, uses the Chain-of-Thought (CoT) process to select the best tool from the configured tools for providing a response to the question. Useful for creating a chatbot that employs RAG. +- [_Conversational agent_](#conversational-agents): Reasons in order to provide a response based on the available knowledge, including the LLM knowledge base and a set of tools provided to the LLM. The LLM reasons iteratively to decide what action to take until it obtains the final answer or reaches the iteration limit. Stores conversation history so that users can ask follow-up questions. The workflow of a conversational agent is variable, based on follow-up questions. For specific questions, uses the Chain-of-Thought (CoT) process to select the best tool from the configured tools for providing a response to the question. Useful for creating a chatbot that employs RAG. ### Flow agents diff --git a/_ml-commons-plugin/agents-tools/tools/connector-tool.md b/_ml-commons-plugin/agents-tools/tools/connector-tool.md new file mode 100644 index 0000000000..dfe4770932 --- /dev/null +++ b/_ml-commons-plugin/agents-tools/tools/connector-tool.md @@ -0,0 +1,168 @@ +--- +layout: default +title: Connector tool +has_children: false +has_toc: false +nav_order: 20 +parent: Tools +grand_parent: Agents and tools +--- + + +# Connector tool +**Introduced 2.15** +{: .label .label-purple } + + +The `ConnectorTool` uses a [connector]({{site.url}}{{site.baseurl}}/ml-commons-plugin/remote-models/connectors/) to call any REST API function. For example, you can use a `ConnectorTool` to call a Lambda function through its REST API interface. + +## Step 1: Register a connector with an execute action + +The `ConnectorTool` can only run an `execute` action within a connector. Before you can create a `ConnectorTool`, you need to configure a connector and provide an `execute` action in the `actions` array. The `execute` action is used to invoke a function at a REST API endpoint. It is similar to the `predict` action, which is used to invoke a machine learning (ML) model. + +For this example, you'll create a connector for a simple AWS Lambda function that accepts two integers and returns their sum. This function is hosted on a dedicated endpoint with a specific URL, which you'll provide in the `url` parameter. For more information, see [Lambda function URLs](https://docs.aws.amazon.com/lambda/latest/dg/lambda-urls.html). + +To create a connector, send the following request: + +```json +POST _plugins/_ml/connectors/_create +{ + "name": "Lambda connector of simple calculator", + "description": "Demo connector of lambda function", + "version": 1, + "protocol": "aws_sigv4", + "parameters": { + "region": "YOUR AWS REGION", + "service_name": "lambda" + }, + "credential": { + "access_key": "YOUR ACCESS KEY", + "secret_key": "YOUR SECRET KEY", + "session_token": "YOUR SESSION TOKEN" + }, + "actions": [ + { + "action_type": "execute", + "method": "POST", + "url": "YOUR LAMBDA FUNCTION URL", + "headers": { + "content-type": "application/json" + }, + "request_body": "{ \"number1\":\"${parameters.number1}\", \"number2\":\"${parameters.number2}\" }" + } + ] +} +``` +{% include copy-curl.html %} + +OpenSearch responds with a connector ID: + +```json +{ + "connector_id": "Zz1XEJABXWrLmr4mewEF" +} +``` + +## Step 2: Register a flow agent that will run the ConnectorTool + +For this example, the Lambda function adds the two input numbers and returns their sum in the `result` field: + +```json +{ + "result": 5 +} +``` + +By default, the `ConnectorTool` expects the response from the Lambda function to contain a field named `response`. However, in this example the Lambda function response doesn't include a `response` field. To retrieve the result from the `result` field instead, you need to provide a `response_filter`, specifying the [JSON path](https://github.com/json-path/JsonPath) to the `result` field (`$.result`). Using the `response_filter`, the `ConnectorTool` will retrieve the result with the specified JSON path and return it in the `response` field. + +To configure the Lambda function workflow, create a flow agent. A flow agent runs a sequence of tools in order and returns the last tool's output. To create a flow agent, send the following register agent request, providing the connector ID from the previous step and a `response_filter`: + +```json +POST /_plugins/_ml/agents/_register +{ + "name": "Demo agent of Lambda connector", + "type": "flow", + "description": "This is a demo agent", + "app_type": "demo", + "tools": [ + { + "type": "ConnectorTool", + "name": "lambda_function", + "parameters": { + "connector_id": "YOUR CONNECTOR ID", + "response_filter": "$.result" + } + } + ] +} +``` +{% include copy-curl.html %} + +For parameter descriptions, see [Register parameters](#register-parameters). + +OpenSearch responds with an agent ID: + +```json +{ + "agent_id": "az1XEJABXWrLmr4miAFj" +} +``` + +## Step 3: Run the agent + +Then, run the agent by sending the following request: + +```json +POST /_plugins/_ml/agents/9X7xWI0Bpc3sThaJdY9i/_execute +{ + "parameters": { + "number1": 2, + "number2": 3 + } +} +``` +{% include copy-curl.html %} + +OpenSearch returns the output of the Lambda function execution. In the output, the field name is `response`, and the `result` field contains the Lambda function result: + +```json +{ + "inference_results": [ + { + "output": [ + { + "name": "response", + "result": 5 + } + ] + } + ] +} +``` + +## Register parameters + +The following table lists all tool parameters that are available when registering an agent. + +Parameter | Type | Required/Optional | Description +:--- | :--- | :--- | :--- +`connector_id` | String | Required | A connector ID of a connector configured with an `execute` action that invokes an API. +`response_filter` | String | Optional | A [JSON path](https://github.com/json-path/JsonPath) to the response field that contains the result of invoking the API. If a `response_filter` is not specified, then the `ConnectorTool` expects the API response to be in a field named `response`. + +## Execute parameters + +When running the agent, you can define any parameter needed for the API call in the `request_body` of your connector's `execute` action. In this example, the parameters are `number1` and `number2`: + +```json +"actions": [ + { + "action_type": "execute", + "method": "POST", + "url": "YOUR LAMBDA FUNCTION URL", + "headers": { + "content-type": "application/json" + }, + "request_body": "{ \"number1\":\"${parameters.number1}\", \"number2\":\"${parameters.number2}\" }" + } + ] +``` \ No newline at end of file diff --git a/_ml-commons-plugin/agents-tools/tools/index.md b/_ml-commons-plugin/agents-tools/tools/index.md index 8db522006e..fba47b63da 100644 --- a/_ml-commons-plugin/agents-tools/tools/index.md +++ b/_ml-commons-plugin/agents-tools/tools/index.md @@ -33,6 +33,7 @@ Each tool takes a list of parameters specific to that tool. In the preceding exa |:--- |:--- | |[`AgentTool`]({{site.url}}{{site.baseurl}}/ml-commons-plugin/agents-tools/tools/agent-tool/) |Runs any agent. | |[`CatIndexTool`]({{site.url}}{{site.baseurl}}/ml-commons-plugin/agents-tools/tools/cat-index-tool/) |Retrieves index information for the OpenSearch cluster. | +|[`ConnectorTool`]({{site.url}}{{site.baseurl}}/ml-commons-plugin/agents-tools/tools/connector-tool/) | Uses a [connector]({{site.url}}{{site.baseurl}}/ml-commons-plugin/remote-models/connectors/) to call any REST API function. | |[`IndexMappingTool`]({{site.url}}{{site.baseurl}}/ml-commons-plugin/agents-tools/tools/index-mapping-tool/) |Retrieves index mapping and setting information for an index. | |[`MLModelTool`]({{site.url}}{{site.baseurl}}/ml-commons-plugin/agents-tools/tools/ml-model-tool/) |Runs machine learning models. | |[`NeuralSparseSearchTool`]({{site.url}}{{site.baseurl}}/ml-commons-plugin/agents-tools/tools/neural-sparse-tool/) | Performs sparse vector retrieval. | diff --git a/_ml-commons-plugin/api/model-apis/register-model.md b/_ml-commons-plugin/api/model-apis/register-model.md index 30cc93be00..61d821419e 100644 --- a/_ml-commons-plugin/api/model-apis/register-model.md +++ b/_ml-commons-plugin/api/model-apis/register-model.md @@ -260,15 +260,24 @@ To register an externally hosted model with guardrails, provide the `guardrails` Field | Data type | Description :--- | :--- | :--- -`type` | String | The guardrail type. Currently, only `local_regex` is supported. -`input_guardrail`| Object | The guardrail for the model input. | -`output_guardrail`| Object | The guardrail for the model output. | -`stop_words`| Object | The list of indexes containing stopwords used for the model input/output validation. If the model prompt/response contains a stopword contained in any of the indexes, the predict request on this model is rejected. | -`index_name`| Object | The name of the index storing the stopwords. | -`source_fields`| Object | The name of the field storing the stopwords. | -`regex`| Object | A regular expression used for input/output validation. If the model prompt/response matches the regular expression, the predict request on this model is rejected. | +`type` | String | The guardrail type. Valid values are [`local_regex`](#example-request-regex-and-stopword-validation) and [`model`](#example-request-guardrail-model-validation). Using `local_regex`, you can specify a regular expression or stop words. Using `model`, you can specify a guardrail model. For more information, see [Guardrails]({{site.url}}{{site.baseurl}}/ml-commons-plugin/remote-models/guardrails/). +`input_guardrail`| Object | The guardrail for the model input. +`output_guardrail`| Object | The guardrail for the model output. +`stop_words`| Object | The list of indexes containing stopwords used for model input/output validation. If the model prompt/response contains a stopword contained in any of the indexes, then the predict request on the model is rejected. +`index_name`| Object | The name of the index storing the stopwords. +`source_fields`| Object | The name of the field storing the stopwords. +`regex`| Object | A regular expression used for input/output validation. If the model prompt/response matches the regular expression, then the predict request on the model is rejected. +`model_id`| String | The guardrail model used to validate user input and LLM output. +`response_filter`| String | The dot path of the field containing the guardrail model response. +`response_validation_regex`| String | The regular expression used to validate the guardrail model response. -#### Example request: Externally hosted model with guardrails +## Examples + +The following examples configure an externally hosted model with guardrails. + +#### Example request: Regex and stopword validation + +The following example uses a regular expression and a set of stopwords to validate the LLM response: ```json POST /_plugins/_ml/models/_register @@ -303,7 +312,36 @@ POST /_plugins/_ml/models/_register ``` {% include copy-curl.html %} -For a complete example, see [Guardrails]({{site.url}}{{site.baseurl}}/ml-commons-plugin/remote-models/guardrails/). +For a complete example, see [Validating input/output using stopwords and regex]({{site.url}}{{site.baseurl}}/ml-commons-plugin/remote-models/guardrails/#validating-inputoutput-using-stopwords-and-regex). + +#### Example request: Guardrail model validation + +The following example uses a guardrail model to validate the LLM response: + +```json +POST /_plugins/_ml/models/_register?deploy=true +{ + "name": "Bedrock Claude V2 model with guardrails model", + "function_name": "remote", + "model_group_id": "ppSmpo8Bi-GZ0tf1i7cD", + "description": "Bedrock Claude V2 model with guardrails model", + "connector_id": "xnJjDZABNFJeYR3IPvTO", + "guardrails": { + "input_guardrail": { + "model_id": "o3JaDZABNFJeYR3I2fRV", + "response_validation_regex": "^\\s*\"[Aa]ccept\"\\s*$" + }, + "output_guardrail": { + "model_id": "o3JaDZABNFJeYR3I2fRV", + "response_validation_regex": "^\\s*\"[Aa]ccept\"\\s*$" + }, + "type": "model" + } +} +``` +{% include copy-curl.html %} + +For a complete example, see [Validating input/output using a guardrail model]({{site.url}}{{site.baseurl}}/ml-commons-plugin/remote-models/guardrails/#validating-inputoutput-using-a-guardrail-model). #### Example response diff --git a/_ml-commons-plugin/api/model-apis/update-model.md b/_ml-commons-plugin/api/model-apis/update-model.md index e952f9f2bb..048b5b76e5 100644 --- a/_ml-commons-plugin/api/model-apis/update-model.md +++ b/_ml-commons-plugin/api/model-apis/update-model.md @@ -64,12 +64,13 @@ PUT /_plugins/_ml/models/T_S-cY0BKCJ3ot9qr0aP ``` {% include copy-curl.html %} -#### Example request: Updating the guardrails +#### Example requests: Updating the guardrails ```json PUT /_plugins/_ml/models/MzcIJX8BA7mbufL6DOwl { "guardrails": { + "type": "local_regex", "input_guardrail": { "stop_words": [ { @@ -93,6 +94,24 @@ PUT /_plugins/_ml/models/MzcIJX8BA7mbufL6DOwl ``` {% include copy-curl.html %} +```json +PUT /_plugins/_ml/models/9uGdCJABjaMXYrp14YRj +{ + "guardrails": { + "type": "model", + "input_guardrail": { + "model_id": "V-G1CJABjaMXYrp1QoUC", + "response_validation_regex": "^\\s*[Aa]ccept\\s*$" + }, + "output_guardrail": { + "model_id": "V-G1CJABjaMXYrp1QoUC", + "response_validation_regex": "^\\s*[Aa]ccept\\s*$" + } + } +} +``` +{% include copy-curl.html %} + #### Example response ```json diff --git a/_ml-commons-plugin/cluster-settings.md b/_ml-commons-plugin/cluster-settings.md index c473af81a1..37c7cab9f7 100644 --- a/_ml-commons-plugin/cluster-settings.md +++ b/_ml-commons-plugin/cluster-settings.md @@ -108,7 +108,7 @@ plugins.ml_commons.sync_up_job_interval_in_seconds: 3 - Default value: `3` - Value range: [0, 86,400] -## Predict monitoring requests +## Monitoring predict requests Controls how many predict requests are monitored on one node. If set to `0`, OpenSearch clears all monitoring predict requests in cache and does not monitor for new predict requests. @@ -303,12 +303,12 @@ This setting automatically redeploys deployed or partially deployed models upon ### Setting ``` -plugins.ml_commons.model_auto_redeploy.enable: false +plugins.ml_commons.model_auto_redeploy.enable: true ``` ### Values -- Default value: false +- Default value: true - Valid values: `false`, `true` ## Set retires for auto redeploy diff --git a/_ml-commons-plugin/index.md b/_ml-commons-plugin/index.md index c936f36161..f0355b6be3 100644 --- a/_ml-commons-plugin/index.md +++ b/_ml-commons-plugin/index.md @@ -30,4 +30,8 @@ ML Commons supports various algorithms to help train ML models and make predicti ## ML Commons API -ML Commons provides its own set of REST APIs. For more information, see [ML Commons API]({{site.url}}{{site.baseurl}}/ml-commons-plugin/api/index/). \ No newline at end of file +ML Commons provides its own set of REST APIs. For more information, see [ML Commons API]({{site.url}}{{site.baseurl}}/ml-commons-plugin/api/index/). + +## Tutorials + +Using the OpenSearch ML framework, you can build various applications, from implementing conversational search to building your own chatbot. For more information, see [Tutorials]({{site.url}}{{site.baseurl}}/ml-commons-plugin/tutorials/index/). \ No newline at end of file diff --git a/_ml-commons-plugin/remote-models/batch-ingestion.md b/_ml-commons-plugin/remote-models/batch-ingestion.md new file mode 100644 index 0000000000..64f434e652 --- /dev/null +++ b/_ml-commons-plugin/remote-models/batch-ingestion.md @@ -0,0 +1,250 @@ +--- +layout: default +title: Batch ingestion +has_children: false +nav_order: 80 +parent: Connecting to externally hosted models +grand_parent: Integrating ML models +--- + +# Using externally hosted ML models for batch ingestion + +**Introduced 2.15** +{: .label .label-purple } + +If you are ingesting multiple documents and generating embeddings by invoking an externally hosted model, you can use batch ingestion to improve performance. + +The [Bulk API]({{site.url}}{{site.baseurl}}/api-reference/document-apis/bulk/) accepts a `batch_size` parameter that specifies to process documents in batches of a specified size. Processors that support batch ingestion will send each batch of documents to an externally hosted model in a single request. + +The [`text_embedding`]({{site.url}}{{site.baseurl}}/ingest-pipelines/processors/text-embedding/) and [`sparse_encoding`]({{site.url}}{{site.baseurl}}/ingest-pipelines/processors/sparse-encoding/) processors currently support batch ingestion. + +## Step 1: Register a model group + +You can register a model in two ways: + +* You can use `model_group_id` to register a model version to an existing model group. +* If you do not use `model_group_id`, then ML Commons creates a model with a new model group. + +To register a model group, send the following request: + +```json +POST /_plugins/_ml/model_groups/_register +{ + "name": "remote_model_group", + "description": "A model group for external models" +} +``` +{% include copy-curl.html %} + +The response contains the model group ID that you'll use to register a model to this model group: + +```json +{ + "model_group_id": "wlcnb4kBJ1eYAeTMHlV6", + "status": "CREATED" +} +``` + +To learn more about model groups, see [Model access control]({{site.url}}{{site.baseurl}}/ml-commons-plugin/model-access-control/). + +## Step 2: Create a connector + +You can create a standalone connector that can be reused for multiple models. Alternatively, you can specify a connector when creating a model so that it can be used only for that model. For more information and example connectors, see [Connectors]({{site.url}}{{site.baseurl}}/ml-commons-plugin/remote-models/connectors/). + +The Connectors Create API, `/_plugins/_ml/connectors/_create`, creates connectors that facilitate registering and deploying external models in OpenSearch. Using the `endpoint` parameter, you can connect ML Commons to any supported ML tool by using its specific API endpoint. For example, you can connect to a ChatGPT model by using the `api.openai.com` endpoint: + +```json +POST /_plugins/_ml/connectors/_create +{ + "name": "OpenAI Chat Connector", + "description": "The connector to public OpenAI model service for GPT 3.5", + "version": 1, + "protocol": "http", + "parameters": { + "endpoint": "api.openai.com", + "model": "gpt-3.5-turbo", + "input_docs_processed_step_size": 100 + }, + "credential": { + "openAI_key": "..." + }, + "actions": [ + { + "action_type": "predict", + "method": "POST", + "url": "https://${parameters.endpoint}/v1/chat/completions", + "headers": { + "Authorization": "Bearer ${credential.openAI_key}" + }, + "request_body": "{ \"model\": \"${parameters.model}\", \"messages\": ${parameters.messages} }" + } + ] +} +``` +{% include copy-curl.html %} + +The `parameters.input_docs_processed_step_size` parameter is used to set the maximum batch size for documents sent to a remote server. You can set this parameter to the maximum batch size supported by the remote server or to a smaller number for optimal performance. + +The response contains the connector ID for the newly created connector: + +```json +{ + "connector_id": "a1eMb4kBJ1eYAeTMAljY" +} +``` + +## Step 3: Register an externally hosted model + +To register an externally hosted model to the model group created in step 1, provide the model group ID from step 1 and the connector ID from step 2 in the following request. You must specify the `function_name` as `remote`: + +```json +POST /_plugins/_ml/models/_register +{ + "name": "openAI-gpt-3.5-turbo", + "function_name": "remote", + "model_group_id": "wlcnb4kBJ1eYAeTMHlV6", + "description": "test model", + "connector_id": "a1eMb4kBJ1eYAeTMAljY" +} +``` +{% include copy-curl.html %} + +OpenSearch returns the task ID of the register operation: + +```json +{ + "task_id": "cVeMb4kBJ1eYAeTMFFgj", + "status": "CREATED" +} +``` + +To check the status of the operation, provide the task ID to the [Tasks API]({{site.url}}{{site.baseurl}}/ml-commons-plugin/api/tasks-apis/get-task/): + +```json +GET /_plugins/_ml/tasks/cVeMb4kBJ1eYAeTMFFgj +``` +{% include copy-curl.html %} + +When the operation is complete, the state changes to `COMPLETED`: + +```json +{ + "model_id": "cleMb4kBJ1eYAeTMFFg4", + "task_type": "REGISTER_MODEL", + "function_name": "REMOTE", + "state": "COMPLETED", + "worker_node": [ + "XPcXLV7RQoi5m8NI_jEOVQ" + ], + "create_time": 1689793598499, + "last_update_time": 1689793598530, + "is_async": false +} +``` + +Take note of the returned `model_id` because you’ll need it to deploy the model. + +## Step 4: Deploy the model + +Starting in OpenSearch version 2.13, externally hosted models are deployed automatically when you send a Predict API request for the first time. To disable automatic deployment for an externally hosted model, set `plugins.ml_commons.model_auto_deploy.enable` to `false`: + +```json +PUT _cluster/settings +{ + "persistent": { + "plugins.ml_commons.model_auto_deploy.enable" : "false" + } +} +``` +{% include copy-curl.html %} + +To undeploy the model, use the [Undeploy API]({{site.url}}{{site.baseurl}}/ml-commons-plugin/api/model-apis/undeploy-model/): + +```json +POST /_plugins/_ml/models/cleMb4kBJ1eYAeTMFFg4/_deploy +``` +{% include copy-curl.html %} + +The response contains the task ID, which you can use to check the status of the deploy operation: + +```json +{ + "task_id": "vVePb4kBJ1eYAeTM7ljG", + "status": "CREATED" +} +``` + +As in the previous step, check the status of the operation by calling the Tasks API: + +```json +GET /_plugins/_ml/tasks/vVePb4kBJ1eYAeTM7ljG +``` +{% include copy-curl.html %} + +When the operation is complete, the state changes to `COMPLETED`: + +```json +{ + "model_id": "cleMb4kBJ1eYAeTMFFg4", + "task_type": "DEPLOY_MODEL", + "function_name": "REMOTE", + "state": "COMPLETED", + "worker_node": [ + "n-72khvBTBi3bnIIR8FTTw" + ], + "create_time": 1689793851077, + "last_update_time": 1689793851101, + "is_async": true +} +``` + +## Step 5: Create an ingest pipeline + +The following example request creates an ingest pipeline with a `text_embedding` processor. The processor converts the text in the `passage_text` field into text embeddings and stores the embeddings in `passage_embedding`: + +```json +PUT /_ingest/pipeline/nlp-ingest-pipeline +{ + "description": "A text embedding pipeline", + "processors": [ + { + "text_embedding": { + "model_id": "cleMb4kBJ1eYAeTMFFg4", + "field_map": { + "passage_text": "passage_embedding" + } + } + } + ] +} +``` +{% include copy-curl.html %} + +## Step 6: Perform bulk indexing + +To ingest documents in bulk, call the Bulk API and provide the `batch_size` and `pipeline` parameters. If you don't provide a `pipeline` parameter, the default ingest pipeline for the index will be used for ingestion: + +```json +POST _bulk?batch_size=5&pipeline=nlp-ingest-pipeline +{ "create": { "_index": "testindex1", "_id": "2" } } +{ "passage_text": "hello world" } +{ "create": { "_index": "testindex1", "_id": "3" } } +{ "passage_text": "big apple" } +{ "create": { "_index": "testindex1", "_id": "4" } } +{ "passage_text": "golden gate bridge" } +{ "create": { "_index": "testindex1", "_id": "5" } } +{ "passage_text": "fine tune" } +{ "create": { "_index": "testindex1", "_id": "6" } } +{ "passage_text": "random test" } +{ "create": { "_index": "testindex1", "_id": "7" } } +{ "passage_text": "sun and moon" } +{ "create": { "_index": "testindex1", "_id": "8" } } +{ "passage_text": "windy" } +{ "create": { "_index": "testindex1", "_id": "9" } } +{ "passage_text": "new york" } +{ "create": { "_index": "testindex1", "_id": "10" } } +{ "passage_text": "fantastic" } + +``` +{% include copy-curl.html %} + diff --git a/_ml-commons-plugin/remote-models/blueprints.md b/_ml-commons-plugin/remote-models/blueprints.md index 0f65aee9da..254a21b068 100644 --- a/_ml-commons-plugin/remote-models/blueprints.md +++ b/_ml-commons-plugin/remote-models/blueprints.md @@ -55,41 +55,45 @@ As an ML developer, you can build connector blueprints for other platforms. Usin ## Configuration parameters -| Field | Data type | Is required | Description | -|:------------------------|:------------|:------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `name` | String | Yes | The name of the connector. | -| `description` | String | Yes | A description of the connector. | -| `version` | Integer | Yes | The version of the connector. | -| `protocol` | String | Yes | The protocol for the connection. For AWS services such as Amazon SageMaker and Amazon Bedrock, use `aws_sigv4`. For all other services, use `http`. | -| `parameters` | JSON object | Yes | The default connector parameters, including `endpoint` and `model`. Any parameters indicated in this field can be overridden by parameters specified in a predict request. | -| `credential` | JSON object | Yes | Defines any credential variables required to connect to your chosen endpoint. ML Commons uses **AES/GCM/NoPadding** symmetric encryption to encrypt your credentials. When the connection to the cluster first starts, OpenSearch creates a random 32-byte encryption key that persists in OpenSearch's system index. Therefore, you do not need to manually set the encryption key. | -| `actions` | JSON array | Yes | Defines what actions can run within the connector. If you're an administrator creating a connection, add the [blueprint]({{site.url}}{{site.baseurl}}/ml-commons-plugin/remote-models/blueprints/) for your desired connection. | -| `backend_roles` | JSON array | Yes | A list of OpenSearch backend roles. For more information about setting up backend roles, see [Assigning backend roles to users]({{site.url}}{{site.baseurl}}/ml-commons-plugin/model-access-control#assigning-backend-roles-to-users). | -| `access_mode` | String | Yes | Sets the access mode for the model, either `public`, `restricted`, or `private`. Default is `private`. For more information about `access_mode`, see [Model groups]({{site.url}}{{site.baseurl}}/ml-commons-plugin/model-access-control#model-groups). | -| `add_all_backend_roles` | Boolean | Yes | When set to `true`, adds all `backend_roles` to the access list, which only a user with admin permissions can adjust. When set to `false`, non-admins can add `backend_roles`. | -| `client_config` | JSON object | No | The client configuration object, which provides settings that control the behavior of the client connections used by the connector. These settings allow you to manage connection limits and timeouts, ensuring efficient and reliable communication. | +| Field | Data type | Is required | Description | +|:---|:---|:---|:---| +| `name` | String | Yes | The name of the connector. | +| `description` | String | Yes | A description of the connector. | +| `version` | Integer | Yes | The version of the connector. | +| `protocol` | String | Yes | The protocol for the connection. For AWS services such as Amazon SageMaker and Amazon Bedrock, use `aws_sigv4`. For all other services, use `http`. | +| `parameters` | JSON object | Yes | The default connector parameters, including `endpoint` and `model`. Any parameters indicated in this field can be overridden by parameters specified in a predict request. | +| `credential` | JSON object | Yes | Defines any credential variables required to connect to your chosen endpoint. ML Commons uses **AES/GCM/NoPadding** symmetric encryption to encrypt your credentials. When the connection to the cluster first starts, OpenSearch creates a random 32-byte encryption key that persists in OpenSearch's system index. Therefore, you do not need to manually set the encryption key. | +| `actions` | JSON array | Yes | Defines what actions can run within the connector. If you're an administrator creating a connection, add the [blueprint]({{site.url}}{{site.baseurl}}/ml-commons-plugin/remote-models/blueprints/) for your desired connection. | +| `backend_roles` | JSON array | Yes | A list of OpenSearch backend roles. For more information about setting up backend roles, see [Assigning backend roles to users]({{site.url}}{{site.baseurl}}/ml-commons-plugin/model-access-control#assigning-backend-roles-to-users). | +| `access_mode` | String | Yes | Sets the access mode for the model, either `public`, `restricted`, or `private`. Default is `private`. For more information about `access_mode`, see [Model groups]({{site.url}}{{site.baseurl}}/ml-commons-plugin/model-access-control#model-groups). | +| `add_all_backend_roles` | Boolean | Yes | When set to `true`, adds all `backend_roles` to the access list, which only a user with admin permissions can adjust. When set to `false`, non-admins can add `backend_roles`. | +| `client_config` | JSON object | No | The client configuration object, which provides settings that control the behavior of the client connections used by the connector. These settings allow you to manage connection limits and timeouts, ensuring efficient and reliable communication. | The `actions` parameter supports the following options. -| Field | Data type | Description | -|:------------------------|:------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `action_type` | String | Required. Sets the ML Commons API operation to use upon connection. As of OpenSearch 2.9, only `predict` is supported. | -| `method` | String | Required. Defines the HTTP method for the API call. Supports `POST` and `GET`. | -| `url` | String | Required. Sets the connection endpoint at which the action occurs. This must match the regex expression for the connection used when [adding trusted endpoints]({{site.url}}{{site.baseurl}}/ml-commons-plugin/remote-models/index#adding-trusted-endpoints). | -| `headers` | JSON object | Sets the headers used inside the request or response body. Default is `ContentType: application/json`. If your third-party ML tool requires access control, define the required `credential` parameters in the `headers` parameter. | -| `request_body` | String | Required. Sets the parameters contained in the request body of the action. The parameters must include `\"inputText\`, which specifies how users of the connector should construct the request payload for the `action_type`. | -| `pre_process_function` | String | Optional. A built-in or custom Painless script used to preprocess the input data. OpenSearch provides the following built-in preprocess functions that you can call directly:
- `connector.pre_process.cohere.embedding` for [Cohere](https://cohere.com/) embedding models
- `connector.pre_process.openai.embedding` for [OpenAI](https://platform.openai.com/docs/guides/embeddings) embedding models
- `connector.pre_process.default.embedding`, which you can use to preprocess documents in neural search requests so that they are in the format that ML Commons can process with the default preprocessor (OpenSearch 2.11 or later). For more information, see [Built-in functions](#built-in-pre--and-post-processing-functions). | -| `post_process_function` | String | Optional. A built-in or custom Painless script used to post-process the model output data. OpenSearch provides the following built-in post-process functions that you can call directly:
- `connector.pre_process.cohere.embedding` for [Cohere text embedding models](https://docs.cohere.com/reference/embed)
- `connector.pre_process.openai.embedding` for [OpenAI text embedding models](https://platform.openai.com/docs/api-reference/embeddings)
- `connector.post_process.default.embedding`, which you can use to post-process documents in the model response so that they are in the format that neural search expects (OpenSearch 2.11 or later). For more information, see [Built-in functions](#built-in-pre--and-post-processing-functions). | +| Field | Data type | Description | +|:---|:---|:---| +| `action_type` | String | Required. Sets the ML Commons API operation to use upon connection. As of OpenSearch 2.9, only `predict` is supported. | +| `method` | String | Required. Defines the HTTP method for the API call. Supports `POST` and `GET`. | +| `url` | String | Required. Sets the connection endpoint at which the action occurs. This must match the regex expression for the connection used when [adding trusted endpoints]({{site.url}}{{site.baseurl}}/ml-commons-plugin/remote-models/index#adding-trusted-endpoints). | +| `headers` | JSON object | Sets the headers used inside the request or response body. Default is `ContentType: application/json`. If your third-party ML tool requires access control, define the required `credential` parameters in the `headers` parameter. | +| `request_body` | String | Required. Sets the parameters contained in the request body of the action. The parameters must include `\"inputText\`, which specifies how users of the connector should construct the request payload for the `action_type`. | +| `pre_process_function` | String | Optional. A built-in or custom Painless script used to preprocess the input data. OpenSearch provides the following built-in preprocess functions that you can call directly:
- `connector.pre_process.cohere.embedding` for [Cohere](https://cohere.com/) embedding models
- `connector.pre_process.openai.embedding` for [OpenAI](https://platform.openai.com/docs/guides/embeddings) embedding models
- `connector.pre_process.default.embedding`, which you can use to preprocess documents in neural search requests so that they are in the format that ML Commons can process with the default preprocessor (OpenSearch 2.11 or later). For more information, see [Built-in functions](#built-in-pre--and-post-processing-functions). | +| `post_process_function` | String | Optional. A built-in or custom Painless script used to post-process the model output data. OpenSearch provides the following built-in post-process functions that you can call directly:
- `connector.pre_process.cohere.embedding` for [Cohere text embedding models](https://docs.cohere.com/reference/embed)
- `connector.pre_process.openai.embedding` for [OpenAI text embedding models](https://platform.openai.com/docs/api-reference/embeddings)
- `connector.post_process.default.embedding`, which you can use to post-process documents in the model response so that they are in the format that neural search expects (OpenSearch 2.11 or later). For more information, see [Built-in functions](#built-in-pre--and-post-processing-functions). | The `client_config` parameter supports the following options. -| Field | Data type | Description | -|:---------------------|:----------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `max_connection` | Integer | The maximum number of concurrent connections that the client can establish with the server. | -| `connection_timeout` | Integer | The maximum amount of time (in seconds) that the client will wait while trying to establish a connection to the server. A timeout prevents the client from waiting indefinitely and allows it to recover from unreachable network endpoints. | -| `read_timeout` | Integer | The maximum amount of time (in seconds) that the client will wait for a response from the server after sending a request. Useful when the server is slow to respond or encounters issues while processing a request. | +| Field | Data type | Description | +|:---|:---|:---| +| `max_connection` | Integer | The maximum number of concurrent connections that the client can establish to the server. Some remote services, like SageMaker, constrain the maximum number of concurrent connections and throw a throttling exception if the number of concurrent connections exceeds the threshold. The maximum number of concurrent OpenSearch connections is `max_connection`*`node_number_for_connector`. To mitigate this issue, try to decrease the value of this parameter and modify the retry settings in `client_config`. Default is `30`. | +| `connection_timeout` | Integer | The maximum amount of time (in seconds) that the client will wait while trying to establish a connection to the server. A timeout prevents the client from waiting indefinitely and allows the client to recover when it encounters unreachable network endpoints. | +| `read_timeout` | Integer | The maximum amount of time (in seconds) that the client will wait for a response from the server after sending a request. This is useful when the server is slow to respond or encounters an issue while processing a request. | +| `retry_backoff_policy` | String | The backoff policy for retries to the remote connector. This is useful when there is spike in traffic causing throttling exceptions. Supported policies are `constant`, `exponential_equal_jitter`, and `exponential_full_jitter`. Default is `constant`. | +| `max_retry_times` | Integer | The maximum number of times that a single remote inference request will be retried. This is useful when there is a spike in traffic causing throttling exceptions. When set to `0`, retrying is disabled. When set to `-1`, OpenSearch does not limit the number of `retry_times`. Setting this to a positive integer specifies the maximum number of retry attempts. Default is `0`. | +| `retry_backoff_millis` | Integer | The base backoff time in milliseconds for retry policy. The suspend time during two retries is determined by this parameter and `retry_backoff_policy`. Default is `200`. | +| `retry_timeout_seconds` | Integer | The timeout value, in seconds, for the retry. If the retry can not succeed within the specified amount of time, the connector will stop retrying and throw an exception. Default is `30`. | ## Built-in pre- and post-processing functions diff --git a/_ml-commons-plugin/remote-models/guardrails.md b/_ml-commons-plugin/remote-models/guardrails.md index ca34eb335c..5330454c8b 100644 --- a/_ml-commons-plugin/remote-models/guardrails.md +++ b/_ml-commons-plugin/remote-models/guardrails.md @@ -1,7 +1,7 @@ --- layout: default title: Guardrails -has_children: false +has_children: true has_toc: false nav_order: 70 parent: Connecting to externally hosted models @@ -14,13 +14,21 @@ grand_parent: Integrating ML models Guardrails can guide a large language model (LLM) toward desired behavior. They act as a filter, preventing the LLM from generating output that is harmful or violates ethical principles and facilitating safer use of AI. Guardrails also cause the LLM to produce more focused and relevant output. -To configure guardrails for your LLM, you can provide a list of words to be prohibited in the input or output of the model. Alternatively, you can provide a regular expression against which the model input or output will be matched. +You can configure guardrails for your LLM using the following methods: +- Provide a list of words to be prohibited in the input or output of the model. Alternatively, you can provide a regular expression against which the model input or output will be matched. For more information, see [Validating input/output using stopwords and regex](#validating-inputoutput-using-stopwords-and-regex). +- Configure a separate LLM whose purpose is to validate the user input and the LLM output. ## Prerequisites Before you start, make sure you have fulfilled the [prerequisites]({{site.url}}{{site.baseurl}}/ml-commons-plugin/remote-models/index/#prerequisites) for connecting to an externally hosted model. -## Step 1: Create a guardrail index +## Validating input/output using stopwords and regex +**Introduced 2.13** +{: .label .label-purple } + +A simple way to validate the user input and LLM output is to provide a set of prohibited words (stopwords) or a regular expression for validation. + +### Step 1: Create a guardrail index To start, create an index that will store the excluded words (_stopwords_). In the index settings, specify a `title` field, which will contain excluded words, and a `query` field of the [percolator]({{site.url}}{{site.baseurl}}/field-types/supported-field-types/percolator/) type. The percolator query will be used to match the LLM input or output: @@ -41,7 +49,7 @@ PUT /words0 ``` {% include copy-curl.html %} -## Step 2: Index excluded words or phrases +### Step 2: Index excluded words or phrases Next, index a query string query that will be used to match excluded words in the model input or output: @@ -71,7 +79,7 @@ PUT /words0/_doc/2?refresh For more query string options, see [Query string query]({{site.url}}{{site.baseurl}}/query-dsl/full-text/query-string/). -## Step 3: Register a model group +### Step 3: Register a model group To register a model group, send the following request: @@ -95,7 +103,7 @@ The response contains the model group ID that you'll use to register a model to To learn more about model groups, see [Model access control]({{site.url}}{{site.baseurl}}/ml-commons-plugin/model-access-control/). -## Step 4: Create a connector +### Step 4: Create a connector Now you can create a connector for the model. In this example, you'll create a connector to the Anthropic Claude model hosted on Amazon Bedrock: @@ -145,7 +153,7 @@ The response contains the connector ID for the newly created connector: } ``` -## Step 5: Register and deploy the model with guardrails +### Step 5: Register and deploy the model with guardrails To register an externally hosted model, provide the model group ID from step 3 and the connector ID from step 4 in the following request. To configure guardrails, include the `guardrails` object: @@ -227,7 +235,7 @@ When the operation is complete, the state changes to `COMPLETED`: } ``` -## Step 6 (Optional): Test the model +### Step 6 (Optional): Test the model To demonstrate how guardrails are applied, first run the predict operation that does not contain any excluded words: @@ -241,7 +249,7 @@ POST /_plugins/_ml/models/p94dYo4BrXGpZpgPp98E/_predict ``` {% include copy-curl.html %} -The response contains inference results: +The response contains the LLM answer: ```json { @@ -293,6 +301,339 @@ The response contains an error message because guardrails were triggered: Guardrails are also triggered when a prompt matches the supplied regular expression. +## Validating input/output using a guardrail model +**Introduced 2.15** +{: .label .label-purple } + +For more advanced validation, you can configure a guardrail model---a separate LLM whose purpose is to validate the user input and the LLM output. In this example, you'll configure two models: +- Chat model: An Anthropic Claude model hosted on Amazon Bedrock whose purpose is to hold a conversation with a user. +- Guardrail model: An OpenAI model whose purpose is to validate the user input and Anthropic Claude output. + +### Step 1: Create a connector for the guardrail model + +First, create a connector to the OpenAI guardrail model. Note that the OpenAI prompt instructs the model to respond only with the words `accept` or `reject`, depending on whether the input/output is acceptable. Additionally, the request contains the `response_filter` parameter, which specifies the field in which the guardrail model will provide the validation result: + +```json +POST /_plugins/_ml/connectors/_create +{ + "name": "openai", + "description": "openai", + "version": "1", + "protocol": "http", + "parameters": { + "endpoint": "api.openai.com", + "max_tokens": 7, + "temperature": 0, + "model": "gpt-3.5-turbo-instruct", + "prompt": "You are a helpful assistant and an expert judge of content quality. Your task is to identify whether the input string below contains content that may be malicious, violent, hateful, sexual, or political in nature. Your answer should consist of a single word, either reject or accept. If the input belongs to any of these categories, please write reject. Otherwise, write accept. \\n\\nHere is the input: ${parameters.question}. \\n\\nYour answer: ", + "response_filter": "$.choices[0].text" + }, + "credential": { + "openAI_key": "" + }, + "actions": [ + { + "action_type": "predict", + "method": "POST", + "url": "https://${parameters.endpoint}/v1/completions", + "headers": { + "Authorization": "Bearer ${credential.openAI_key}" + }, + "request_body": "{ \"model\": \"${parameters.model}\", \"prompt\": \"${parameters.prompt}\", \"max_tokens\": ${parameters.max_tokens}, \"temperature\": ${parameters.temperature} }" + } + ] +} +``` +{% include copy-curl.html %} + +The response contains the connector ID used in the next steps: + +```json +{ + "connector_id": "j3JVDZABNFJeYR3IVPRz" +} +``` + +### Step 2: Register a model group for the guardrail model + +To register a model group for the OpenAI guardrail model, send the following request: + +```json +POST /_plugins/_ml/model_groups/_register +{ + "name": "guardrail model group", + "description": "This is a guardrail model group." +} +``` +{% include copy-curl.html %} + +The response contains the model group ID used to register a model to this model group: + +```json +{ + "model_group_id": "ppSmpo8Bi-GZ0tf1i7cD", + "status": "CREATED" +} +``` + +To learn more about model groups, see [Model access control]({{site.url}}{{site.baseurl}}/ml-commons-plugin/model-access-control/). + +### Step 3: Register and deploy the guardrail model + +Using the connector ID and the model group ID, register and deploy the OpenAI guardrail model: + +```json +POST /_plugins/_ml/models/_register?deploy=true +{ + "name": "openai guardrails model", + "function_name": "remote", + "model_group_id": "ppSmpo8Bi-GZ0tf1i7cD", + "description": "guardrails test model", + "connector_id": "j3JVDZABNFJeYR3IVPRz" +} +``` +{% include copy-curl.html %} + +OpenSearch returns the task ID of the register operation and the model ID of the registered model: + +```json +{ + "task_id": "onJaDZABNFJeYR3I2fQ1", + "status": "CREATED", + "model_id": "o3JaDZABNFJeYR3I2fRV" +} +``` + +To check the status of the operation, provide the task ID to the [Tasks API]({{site.url}}{{site.baseurl}}/ml-commons-plugin/api/tasks-apis/get-task/): + +```bash +GET /_plugins/_ml/tasks/onJaDZABNFJeYR3I2fQ1 +``` +{% include copy-curl.html %} + +When the operation is complete, the state changes to `COMPLETED`: + +```json +{ + "model_id": "o3JaDZABNFJeYR3I2fRV", + "task_type": "DEPLOY_MODEL", + "function_name": "REMOTE", + "state": "COMPLETED", + "worker_node": [ + "n-72khvBTBi3bnIIR8FTTw" + ], + "create_time": 1689793851077, + "last_update_time": 1689793851101, + "is_async": true +} +``` + +### Step 4 (Optional): Test the guardrail model + +You can test the guardrail model user input validation by sending requests that do and do not contain offensive words. + +First, send a request that does not contain offensive words: + +```json +POST /_plugins/_ml/models/o3JaDZABNFJeYR3I2fRV/_predict +{ + "parameters": { + "question": "how many indices do i have in my cluster" + } +} +``` +{% include copy-curl.html %} + +The guardrail model accepts the preceding request: + +```json +{ + "inference_results": [ + { + "output": [ + { + "name": "response", + "dataAsMap": { + "response": "accept" + } + } + ], + "status_code": 200 + } + ] +} +``` + +Next, send a request that contains offensive words: + +```json +POST /_plugins/_ml/models/o3JaDZABNFJeYR3I2fRV/_predict +{ + "parameters": { + "question": "how to rob a bank" + } +} +``` +{% include copy-curl.html %} + +The guardrail model rejects the preceding request: + +```json +{ + "inference_results": [ + { + "output": [ + { + "name": "response", + "dataAsMap": { + "response": "reject" + } + } + ], + "status_code": 200 + } + ] +} +``` + +### Step 5: Create a connector for the chat model + +In this example, the chat model will be an Anthropic Claude model hosted on Amazon Bedrock. To create a connector for the model, send the following request. Note that the `response_filter` parameter specifies the field in which the guardrail model will provide the validation result: + +```json +POST /_plugins/_ml/connectors/_create +{ + "name": "BedRock claude Connector", + "description": "BedRock claude Connector", + "version": 1, + "protocol": "aws_sigv4", + "parameters": { + "region": "us-east-1", + "service_name": "bedrock", + "anthropic_version": "bedrock-2023-05-31", + "endpoint": "bedrock.us-east-1.amazonaws.com", + "auth": "Sig_V4", + "content_type": "application/json", + "max_tokens_to_sample": 8000, + "temperature": 0.0001, + "response_filter": "$.completion" + }, + "credential": { + "access_key": "", + "secret_key": "" + }, + "actions": [ + { + "action_type": "predict", + "method": "POST", + "url": "https://bedrock-runtime.us-east-1.amazonaws.com/model/anthropic.claude-v2/invoke", + "headers": { + "content-type": "application/json", + "x-amz-content-sha256": "required" + }, + "request_body": "{\"prompt\":\"${parameters.prompt}\", \"max_tokens_to_sample\":${parameters.max_tokens_to_sample}, \"temperature\":${parameters.temperature}, \"anthropic_version\":\"${parameters.anthropic_version}\" }" + } + ] +} +``` +{% include copy-curl.html %} + +The response contains the connector ID used in the next steps: + +```json +{ + "connector_id": "xnJjDZABNFJeYR3IPvTO" +} +``` + +### Step 6: Register and deploy the chat model with guardrails + +To register and deploy the Anthropic Claude chat model, send the following request. Note that the `guardrails` object contains a `response_validation_regex` parameter that specifies to only treat the input/output as valid if the guardrail model responds with a variant of the word `accept`: + +```json +POST /_plugins/_ml/models/_register?deploy=true +{ + "name": "Bedrock Claude V2 model with openai guardrails model", + "function_name": "remote", + "model_group_id": "ppSmpo8Bi-GZ0tf1i7cD", + "description": "Bedrock Claude V2 model with openai guardrails model", + "connector_id": "xnJjDZABNFJeYR3IPvTO", + "guardrails": { + "input_guardrail": { + "model_id": "o3JaDZABNFJeYR3I2fRV", + "response_validation_regex": "^\\s*\"[Aa]ccept\"\\s*$" + }, + "output_guardrail": { + "model_id": "o3JaDZABNFJeYR3I2fRV", + "response_validation_regex": "^\\s*\"[Aa]ccept\"\\s*$" + }, + "type": "model" + } +} +``` +{% include copy-curl.html %} + +OpenSearch returns the task ID of the register operation and the model ID of the registered model: + +```json +{ + "task_id": "1nJnDZABNFJeYR3IvfRL", + "status": "CREATED", + "model_id": "43JqDZABNFJeYR3IQPQH" +} +``` + +### Step 7 (Optional): Test the chat model with guardrails + +You can test the Anthropic Claude chat model with guardrails by sending predict requests that do and do not contain offensive words. + +First, send a request that does not contain offensive words: + +```json +POST /_plugins/_ml/models/43JqDZABNFJeYR3IQPQH/_predict +{ + "parameters": { + "prompt": "\n\nHuman:${parameters.question}\n\nnAssistant:", + "question": "hello" + } +} +``` +{% include copy-curl.html %} + +OpenSearch responds with the LLM answer: + +```json +{ + "inference_results": [ + { + "output": [ + { + "name": "response", + "dataAsMap": { + "response": " Hello!" + } + } + ], + "status_code": 200 + } + ] +} +``` + +Next, send a request that contains offensive words: + +```json +POST /_plugins/_ml/models/43JqDZABNFJeYR3IQPQH/_predict +{ + "parameters": { + "prompt": "\n\nHuman:${parameters.question}\n\nnAssistant:", + "question": "how to rob a bank" + } +} +``` + +OpenSearch responds with an error. + ## Next steps - For more information about configuring guardrails, see [The `guardrails` parameter]({{site.url}}{{site.baseurl}}/ml-commons-plugin/api/model-apis/register-model/#the-guardrails-parameter). \ No newline at end of file diff --git a/_ml-commons-plugin/remote-models/index.md b/_ml-commons-plugin/remote-models/index.md index a067a0b397..ddde42ecec 100644 --- a/_ml-commons-plugin/remote-models/index.md +++ b/_ml-commons-plugin/remote-models/index.md @@ -317,12 +317,15 @@ The response contains the inference results provided by the OpenAI model: ] } ``` +## Step 6: Use the model for batch ingestion -## Step 6: Use the model for search +To learn how to use the model for batch ingestion in order to improve ingestion performance, see [Using externally hosted ML models for batch ingestion]({{site.url}}{{site.baseurl}}/ml-commons-plugin/remote-models/batch-ingestion/). + +## Step 7: Use the model for search To learn how to use the model for vector search, see [Using an ML model for neural search]({{site.url}}{{site.baseurl}}/search-plugins/neural-search/#using-an-ml-model-for-neural-search). -## Step 7 (Optional): Undeploy the model +## Step 8 (Optional): Undeploy the model You can undeploy the model automatically by defining a TTL in the model settings or by using the Undeploy API to undeploy the model manually. For more information, see [Undeploy API]({{site.url}}{{site.baseurl}}/ml-commons-plugin/api/model-apis/undeploy-model/). diff --git a/_ml-commons-plugin/tutorials/build-chatbot.md b/_ml-commons-plugin/tutorials/build-chatbot.md new file mode 100644 index 0000000000..1e51298106 --- /dev/null +++ b/_ml-commons-plugin/tutorials/build-chatbot.md @@ -0,0 +1,910 @@ +--- +layout: default +title: Build your own chatbot +parent: Tutorials +nav_order: 60 +--- + +# Build your own chatbot + +This is an experimental feature and is not recommended for use in a production environment. For updates on the progress of the feature or if you want to leave feedback, see the associated [GitHub issue](https://github.com/opensearch-project/ml-commons/issues/1161). +{: .warning} + +Sometimes a large language model (LLM) cannot answer a question right away. For example, an LLM can't tell you how many errors there are in your log index for last week because its knowledge base does not contain your proprietary data. In this case, you need to provide additional information to an LLM in a subsequent call. You can use an agent to solve such complex problems. The agent can run tools to obtain more information from configured data sources and send the additional information to the LLM as context. + +This tutorial describes how to build your own chatbot in OpenSearch using a `conversational` agent. For more information about agents, see [Agents and tools]({{site.url}}{{site.baseurl}}/ml-commons-plugin/agents-tools/index/). + +Replace the placeholders starting with the prefix `your_` with your own values. +{: .note} + +## Prerequisite + +Log in to the OpenSearch Dashboards home page, select **Add sample data**, and add the **Sample eCommerce orders** data. + +## Step 1: Configure a knowledge base + +Meet the prerequisite and follow Step 1 of the [RAG with a conversational flow agent tutorial]({{site.url}}{{site.baseurl}}/ml-commons-plugin/tutorials/rag-conversational-agent/) to configure the `test_population_data` knowledge base index, which contains US city population data. + +Create an ingest pipeline: + +```json +PUT /_ingest/pipeline/test_stock_price_data_pipeline +{ + "description": "text embedding pipeline", + "processors": [ + { + "text_embedding": { + "model_id": "your_text_embedding_model_id", + "field_map": { + "stock_price_history": "stock_price_history_embedding" + } + } + } + ] +} +``` +{% include copy-curl.html %} + +Create the `test_stock_price_data` index, which contains historical stock price data: + +```json +PUT test_stock_price_data +{ + "mappings": { + "properties": { + "stock_price_history": { + "type": "text" + }, + "stock_price_history_embedding": { + "type": "knn_vector", + "dimension": 384 + } + } + }, + "settings": { + "index": { + "knn.space_type": "cosinesimil", + "default_pipeline": "test_stock_price_data_pipeline", + "knn": "true" + } + } +} +``` +{% include copy-curl.html %} + +Ingest data into the index: + +```json +POST _bulk +{"index": {"_index": "test_stock_price_data"}} +{"stock_price_history": "This is the historical montly stock price record for Amazon.com, Inc. (AMZN) with CSV format.\nDate,Open,High,Low,Close,Adj Close,Volume\n2023-03-01,93.870003,103.489998,88.120003,103.290001,103.290001,1349240300\n2023-04-01,102.300003,110.860001,97.709999,105.449997,105.449997,1224083600\n2023-05-01,104.949997,122.919998,101.150002,120.580002,120.580002,1432891600\n2023-06-01,120.690002,131.490005,119.930000,130.360001,130.360001,1242648800\n2023-07-01,130.820007,136.649994,125.919998,133.679993,133.679993,1058754800\n2023-08-01,133.550003,143.630005,126.410004,138.009995,138.009995,1210426200\n2023-09-01,139.460007,145.860001,123.040001,127.120003,127.120003,1120271900\n2023-10-01,127.279999,134.479996,118.349998,133.089996,133.089996,1224564700\n2023-11-01,133.960007,149.259995,133.710007,146.089996,146.089996,1025986900\n2023-12-01,146.000000,155.630005,142.809998,151.940002,151.940002,931128600\n2024-01-01,151.539993,161.729996,144.050003,155.199997,155.199997,953344900\n2024-02-01,155.869995,175.000000,155.619995,174.449997,174.449997,437720800\n"} +{"index": {"_index": "test_stock_price_data"}} +{"stock_price_history": "This is the historical montly stock price record for Apple Inc. (AAPL) with CSV format.\nDate,Open,High,Low,Close,Adj Close,Volume\n2023-03-01,146.830002,165.000000,143.899994,164.899994,164.024475,1520266600\n2023-04-01,164.270004,169.850006,159.779999,169.679993,168.779099,969709700\n2023-05-01,169.279999,179.350006,164.309998,177.250000,176.308914,1275155500\n2023-06-01,177.699997,194.479996,176.929993,193.970001,193.207016,1297101100\n2023-07-01,193.779999,198.229996,186.600006,196.449997,195.677261,996066400\n2023-08-01,196.240005,196.729996,171.960007,187.869995,187.130997,1322439400\n2023-09-01,189.490005,189.979996,167.619995,171.210007,170.766846,1337586600\n2023-10-01,171.220001,182.339996,165.669998,170.770004,170.327972,1172719600\n2023-11-01,171.000000,192.929993,170.119995,189.949997,189.458313,1099586100\n2023-12-01,190.330002,199.619995,187.449997,192.529999,192.284637,1062774800\n2024-01-01,187.149994,196.380005,180.169998,184.399994,184.164993,1187219300\n2024-02-01,183.990005,191.050003,179.250000,188.850006,188.609329,420063900\n"} +{"index": {"_index": "test_stock_price_data"}} +{"stock_price_history": "This is the historical montly stock price record for NVIDIA Corporation (NVDA) with CSV format.\nDate,Open,High,Low,Close,Adj Close,Volume\n2023-03-01,231.919998,278.339996,222.970001,277.769989,277.646820,1126373100\n2023-04-01,275.089996,281.100006,262.200012,277.489990,277.414032,743592100\n2023-05-01,278.399994,419.380005,272.399994,378.339996,378.236420,1169636000\n2023-06-01,384.890015,439.899994,373.559998,423.019989,422.904175,1052209200\n2023-07-01,425.170013,480.880005,413.459991,467.290009,467.210449,870489500\n2023-08-01,464.600006,502.660004,403.109985,493.549988,493.465942,1363143600\n2023-09-01,497.619995,498.000000,409.799988,434.989990,434.915924,857510100\n2023-10-01,440.299988,476.089996,392.299988,407.799988,407.764130,1013917700\n2023-11-01,408.839996,505.480011,408.690002,467.700012,467.658905,914386300\n2023-12-01,465.250000,504.329987,450.100006,495.220001,495.176453,740951700\n2024-01-01,492.440002,634.929993,473.200012,615.270020,615.270020,970385300\n2024-02-01,621.000000,721.849976,616.500000,721.330017,721.330017,355346500\n"} +{"index": {"_index": "test_stock_price_data"}} +{"stock_price_history": "This is the historical montly stock price record for Meta Platforms, Inc. (META) with CSV format.\n\nDate,Open,High,Low,Close,Adj Close,Volume\n2023-03-01,174.589996,212.169998,171.429993,211.940002,211.940002,690053000\n2023-04-01,208.839996,241.690002,207.130005,240.320007,240.320007,446687900\n2023-05-01,238.619995,268.649994,229.850006,264.720001,264.720001,486968500\n2023-06-01,265.899994,289.790009,258.880005,286.980011,286.980011,480979900\n2023-07-01,286.700012,326.200012,284.850006,318.600006,318.600006,624605100\n2023-08-01,317.540009,324.140015,274.380005,295.890015,295.890015,423147800\n2023-09-01,299.369995,312.869995,286.790009,300.209991,300.209991,406686600\n2023-10-01,302.739990,330.540009,279.399994,301.269989,301.269989,511307900\n2023-11-01,301.850006,342.920013,301.850006,327.149994,327.149994,329270500\n2023-12-01,325.480011,361.899994,313.660004,353.959991,353.959991,332813800\n2024-01-01,351.320007,406.359985,340.010010,390.140015,390.140015,347020200\n2024-02-01,393.940002,485.959991,393.049988,473.279999,473.279999,294260900\n"} +{"index": {"_index": "test_stock_price_data"}} +{"stock_price_history": "This is the historical montly stock price record for Microsoft Corporation (MSFT) with CSV format.\n\nDate,Open,High,Low,Close,Adj Close,Volume\n2023-03-01,250.759995,289.269989,245.610001,288.299988,285.953064,747635000\n2023-04-01,286.519989,308.929993,275.369995,307.260010,304.758759,551497100\n2023-05-01,306.970001,335.940002,303.399994,328.390015,325.716766,600807200\n2023-06-01,325.929993,351.470001,322.500000,340.540009,338.506226,547588700\n2023-07-01,339.190002,366.779999,327.000000,335.920013,333.913818,666764400\n2023-08-01,335.190002,338.540009,311.549988,327.760010,325.802582,479456700\n2023-09-01,331.309998,340.859985,309.450012,315.750000,314.528809,416680700\n2023-10-01,316.279999,346.200012,311.209991,338.109985,336.802307,540907000\n2023-11-01,339.790009,384.299988,339.649994,378.910004,377.444519,563880300\n2023-12-01,376.760010,378.160004,362.899994,376.040009,375.345886,522003700\n2024-01-01,373.859985,415.320007,366.500000,397.579987,396.846130,528399000\n2024-02-01,401.829987,420.820007,401.799988,409.489990,408.734131,237639700\n"} +{"index": {"_index": "test_stock_price_data"}} +{"stock_price_history": "This is the historical montly stock price record for Alphabet Inc. (GOOG) with CSV format.\n\nDate,Open,High,Low,Close,Adj Close,Volume\n2023-03-01,90.160004,107.510002,89.769997,104.000000,104.000000,725477100\n2023-04-01,102.669998,109.629997,102.379997,108.220001,108.220001,461670700\n2023-05-01,107.720001,127.050003,104.500000,123.370003,123.370003,620317400\n2023-06-01,123.500000,129.550003,116.910004,120.970001,120.970001,521386300\n2023-07-01,120.320000,134.070007,115.830002,133.110001,133.110001,525456900\n2023-08-01,130.854996,138.399994,127.000000,137.350006,137.350006,463482000\n2023-09-01,138.429993,139.929993,128.190002,131.850006,131.850006,389593900\n2023-10-01,132.154999,142.380005,121.459999,125.300003,125.300003,514877100\n2023-11-01,125.339996,141.100006,124.925003,133.919998,133.919998,405635900\n2023-12-01,133.320007,143.945007,129.399994,140.929993,140.929993,482059400\n2024-01-01,139.600006,155.199997,136.850006,141.800003,141.800003,428771200\n2024-02-01,143.690002,150.695007,138.169998,147.139999,147.139999,231934100\n"} +``` +{% include copy-curl.html %} + +## Step 2: Prepare an LLM + +This tutorial uses the [Amazon Bedrock Claude model](https://aws.amazon.com/bedrock/claude/). You can also use other LLMs. For more information, see [Connecting to externally hosted models]({{site.url}}{{site.baseurl}}/ml-commons-plugin/remote-models/index/). + +Create a connector for the model: + +```json +POST /_plugins/_ml/connectors/_create +{ + "name": "BedRock Claude instant-v1 Connector ", + "description": "The connector to BedRock service for claude model", + "version": 1, + "protocol": "aws_sigv4", + "parameters": { + "region": "us-east-1", + "service_name": "bedrock", + "anthropic_version": "bedrock-2023-05-31", + "max_tokens_to_sample": 8000, + "temperature": 0.0001, + "response_filter": "$.completion", + "stop_sequences": ["\n\nHuman:","\nObservation:","\n\tObservation:","\nObservation","\n\tObservation","\n\nQuestion"] + }, + "credential": { + "access_key": "your_aws_access_key", + "secret_key": "your_aws_secret_key", + "session_token": "your_aws_session_token" + }, + "actions": [ + { + "action_type": "predict", + "method": "POST", + "url": "https://bedrock-runtime.us-east-1.amazonaws.com/model/anthropic.claude-instant-v1/invoke", + "headers": { + "content-type": "application/json", + "x-amz-content-sha256": "required" + }, + "request_body": "{\"prompt\":\"${parameters.prompt}\", \"stop_sequences\": ${parameters.stop_sequences}, \"max_tokens_to_sample\":${parameters.max_tokens_to_sample}, \"temperature\":${parameters.temperature}, \"anthropic_version\":\"${parameters.anthropic_version}\" }" + } + ] +} +``` +{% include copy-curl.html %} + +Note the connector ID; you'll use it to register the model. + +Register the model: + +```json +POST /_plugins/_ml/models/_register +{ + "name": "Bedrock Claude Instant model", + "function_name": "remote", + "description": "Bedrock Claude instant-v1 model", + "connector_id": "your_connector_id" +} +``` +{% include copy-curl.html %} + +Note the LLM model ID; you'll use it in the following steps. + +Deploy the model: + +```json +POST /_plugins/_ml/models/your_LLM_model_id/_deploy +``` +{% include copy-curl.html %} + +Test the model: + +```json +POST /_plugins/_ml/models/your_LLM_model_id/_predict +{ + "parameters": { + "prompt": "\n\nHuman: how are you? \n\nAssistant:" + } +} +``` +{% include copy-curl.html %} + +## Step 3: Create an agent with the default prompt + +Next, create and test an agent. + +### Create an agent + +Create an agent of the `conversational` type. + +The agent is configured with the following information: + +- Meta information: `name`, `type`, `description`. +- LLM information: The agent uses an LLM to reason and select the next step, including choosing an appropriate tool and preparing the tool input. +- Tools: A tool is a function that can be executed by the agent. Each tool can define its own `name`, `description`, and `parameters`. +- Memory: Stores chat messages. Currently, OpenSearch only supports one memory type: `conversation_index`. + +The agent contains the following parameters: + +- `conversational`: This agent type has a built-in prompt. To override it with your own prompt, see [Step 4](#step-4-optional-create-an-agent-with-a-custom-prompt). +- `app_type`: Specify this parameter for reference purposes in order to differentiate between multiple agents. +- `llm`: Defines the LLM configuration: + - `"max_iteration": 5`: The agent runs the LLM a maximum of five times. + - `"response_filter": "$.completion"`: Needed to retrieve the LLM answer from the Bedrock Claude model response. + - `"message_history_limit": 5`: The agent retrieves a maximum of the five most recent historical messages and adds them to the LLM context. Set this parameter to `0` to omit message history in the context. + - `disable_trace`: If `true`, then the agent does not store trace data in memory. Trace data is included in each message and provides a detailed recount of steps performed while generating the message. +- `memory`: Defines how to store messages. Currently, OpenSearch only supports the `conversation_index` memory, which stores messages in a memory index. +- Tools: + - An LLM will reason to decide which tool to run and will prepare the tool's input. + - To include the tool's output in the response, specify `"include_output_in_agent_response": true`. In this tutorial, you will include the `PPLTool` output in the response (see the example response in [Test the agent](#test-the-agent)). + - By default, the tool's `name` is the same as the tool's `type`, and each tool has a default description. You can override the tool's `name` and `description`. + - Each tool in the `tools` list must have a unique name. For example, the following demo agent defines two tools of the `VectorDBTool` type with different names (`population_data_knowledge_base` and `stock_price_data_knowledge_base`). Each tool has a custom description so that the LLM can easily understand what the tool does. + + For more information about tools, see [Tools]({{site.url}}{{site.baseurl}}/ml-commons-plugin/agents-tools/tools/index/). + +This example request configures several sample tools in an agent. You can configure other tools that are relevant to your use case as needed. +{: .note} + +Register the agent: + +```json +POST _plugins/_ml/agents/_register +{ + "name": "Chat Agent with Claude", + "type": "conversational", + "description": "this is a test agent", + "app_type": "os_chat", + "llm": { + "model_id": "your_llm_model_id_from_step2", + "parameters": { + "max_iteration": 5, + "response_filter": "$.completion", + "message_history_limit": 5, + "disable_trace": false + } + }, + "memory": { + "type": "conversation_index" + }, + "tools": [ + { + "type": "PPLTool", + "parameters": { + "model_id": "your_llm_model_id_from_step2", + "model_type": "CLAUDE", + "execute": true + }, + "include_output_in_agent_response": true + }, + { + "type": "VisualizationTool", + "parameters": { + "index": ".kibana" + }, + "include_output_in_agent_response": true + }, + { + "type": "VectorDBTool", + "name": "population_data_knowledge_base", + "description": "This tool provide population data of US cities.", + "parameters": { + "input": "${parameters.question}", + "index": "test_population_data", + "source_field": [ + "population_description" + ], + "model_id": "your_embedding_model_id_from_step1", + "embedding_field": "population_description_embedding", + "doc_size": 3 + } + }, + { + "type": "VectorDBTool", + "name": "stock_price_data_knowledge_base", + "description": "This tool provide stock price data.", + "parameters": { + "input": "${parameters.question}", + "index": "test_stock_price_data", + "source_field": [ + "stock_price_history" + ], + "model_id": "your_embedding_model_id_from_step1", + "embedding_field": "stock_price_history_embedding", + "doc_size": 3 + } + }, + { + "type": "CatIndexTool", + "description": "Use this tool to get OpenSearch index information: (health, status, index, uuid, primary count, replica count, docs.count, docs.deleted, store.size, primary.store.size). \nIt takes 2 optional arguments named `index` which is a comma-delimited list of one or more indices to get information from (default is an empty list meaning all indices), and `local` which means whether to return information from the local node only instead of the cluster manager node (default is false)." + }, + { + "type": "SearchAnomalyDetectorsTool" + }, + { + "type": "SearchAnomalyResultsTool" + }, + { + "type": "SearchMonitorsTool" + }, + { + "type": "SearchAlertsTool" + } + ] +} +``` +{% include copy-curl.html %} + +Note the agent ID; you'll use it in the next step. + +### Test the agent + +Note the following testing tips: + +- You can view the detailed steps of an agent execution in one of the following ways: + - Enable verbose mode: `"verbose": true`. + - Call the Get Trace API: `GET _plugins/_ml/memory/message/your_message_id/traces`. + +- An LLM may hallucinate. It may choose the wrong tool to solve your problem, especially when you have configured many tools. To avoid hallucinations, try the following options: + - Avoid configuring many tools in an agent. + - Provide a detailed tool description clarifying what the tool can do. + - Specify the tool to use in the LLM question, for example, `Can you use the PPLTool to query the opensearch_dashboards_sample_data_ecommerce index so it can calculate how many orders were placed last week?`. + - Specify the tool to use when executing an agent. For example, specify that only `PPLTool` and `CatIndexTool` should be used to process the current request. + +Test the agent: + +```json +POST _plugins/_ml/agents/your_agent_id/_execute +{ + "parameters": { + "question": "Can you query with index opensearch_dashboards_sample_data_ecommerce to calculate how many orders in last week?", + "verbose": false, + "selected_tools": ["PPLTool", "CatIndexTool"] + } +} +``` +{% include copy-curl.html %} + + +#### Test the PPLTool + + +```json +POST _plugins/_ml/agents/your_agent_id/_execute +{ + "parameters": { + "question": "Can you query with index opensearch_dashboards_sample_data_ecommerce to calculate how many orders in last week?", + "verbose": false + } +} +``` +{% include copy-curl.html %} + +Because you specified `"include_output_in_agent_response": true` for the `PPLTool`, the response contains `PPLTool.output` in the `additional_info` object: + +```json +{ + "inference_results": [ + { + "output": [ + { + "name": "memory_id", + "result": "TkJwyI0Bn3OCesyvzuH9" + }, + { + "name": "parent_interaction_id", + "result": "T0JwyI0Bn3OCesyvz-EI" + }, + { + "name": "response", + "dataAsMap": { + "response": "The tool response from the PPLTool shows that there were 3812 orders in the opensearch_dashboards_sample_data_ecommerce index within the last week.", + "additional_info": { + "PPLTool.output": [ + """{"ppl":"source\u003dopensearch_dashboards_sample_data_ecommerce| where order_date \u003e DATE_SUB(NOW(), INTERVAL 1 WEEK) | stats COUNT() AS count","executionResult":"{\n \"schema\": [\n {\n \"name\": \"count\",\n \"type\": \"integer\"\n }\n ],\n \"datarows\": [\n [\n 3812\n ]\n ],\n \"total\": 1,\n \"size\": 1\n}"}""" + ] + } + } + } + ] + } + ] +} +``` +{% include copy-curl.html %} + +Obtain trace data: + +```json +GET _plugins/_ml/memory/message/T0JwyI0Bn3OCesyvz-EI/traces +``` +{% include copy-curl.html %} + + +#### Test the population_data_knowledge_base VectorDBTool + + +To view detailed steps, set `verbose` to `true` when executing the agent: + +```json +POST _plugins/_ml/agents/your_agent_id/_execute +{ + "parameters": { + "question": "What's the population increase of Seattle from 2021 to 2023?", + "verbose": true + } +} +``` +{% include copy-curl.html %} + +The response contains the execution steps: + +```json +{ + "inference_results": [ + { + "output": [ + { + "name": "memory_id", + "result": "LkJuyI0Bn3OCesyv3-Ef" + }, + { + "name": "parent_interaction_id", + "result": "L0JuyI0Bn3OCesyv3-Er" + }, + { + "name": "response", + "result": """{ + "thought": "Let me check the population data tool", + "action": "population_data_knowledge_base", + "action_input": "{'question': 'What is the population increase of Seattle from 2021 to 2023?', 'cities': ['Seattle']}" +}""" + }, + { + "name": "response", + "result": """{"_index":"test_population_data","_source":{"population_description":"Chart and table of population level and growth rate for the Seattle metro area from 1950 to 2023. United Nations population projections are also included through the year 2035.\\nThe current metro area population of Seattle in 2023 is 3,519,000, a 0.86% increase from 2022.\\nThe metro area population of Seattle in 2022 was 3,489,000, a 0.81% increase from 2021.\\nThe metro area population of Seattle in 2021 was 3,461,000, a 0.82% increase from 2020.\\nThe metro area population of Seattle in 2020 was 3,433,000, a 0.79% increase from 2019."},"_id":"9EJsyI0Bn3OCesyvU-B7","_score":0.75154537} +{"_index":"test_population_data","_source":{"population_description":"Chart and table of population level and growth rate for the Austin metro area from 1950 to 2023. United Nations population projections are also included through the year 2035.\\nThe current metro area population of Austin in 2023 is 2,228,000, a 2.39% increase from 2022.\\nThe metro area population of Austin in 2022 was 2,176,000, a 2.79% increase from 2021.\\nThe metro area population of Austin in 2021 was 2,117,000, a 3.12% increase from 2020.\\nThe metro area population of Austin in 2020 was 2,053,000, a 3.43% increase from 2019."},"_id":"80JsyI0Bn3OCesyvU-B7","_score":0.6689899} +{"_index":"test_population_data","_source":{"population_description":"Chart and table of population level and growth rate for the New York City metro area from 1950 to 2023. United Nations population projections are also included through the year 2035.\\nThe current metro area population of New York City in 2023 is 18,937,000, a 0.37% increase from 2022.\\nThe metro area population of New York City in 2022 was 18,867,000, a 0.23% increase from 2021.\\nThe metro area population of New York City in 2021 was 18,823,000, a 0.1% increase from 2020.\\nThe metro area population of New York City in 2020 was 18,804,000, a 0.01% decline from 2019."},"_id":"8EJsyI0Bn3OCesyvU-B7","_score":0.66782206} +""" + }, + { + "name": "response", + "result": "According to the population data tool, the population of Seattle increased by approximately 28,000 people from 2021 to 2023, which is a 0.82% increase from 2021 to 2022 and a 0.86% increase from 2022 to 2023." + } + ] + } + ] +} +``` + +Obtain trace data: + +```json +GET _plugins/_ml/memory/message/L0JuyI0Bn3OCesyv3-Er/traces +``` +{% include copy-curl.html %} + +#### Test conversational memory + +To continue the same conversation, specify the conversation's `memory_id` when executing the agent: + +```json +POST _plugins/_ml/agents/your_agent_id/_execute +{ + "parameters": { + "question": "What's the population of Austin 2023, compare with Seattle", + "memory_id": "LkJuyI0Bn3OCesyv3-Ef", + "verbose": true + } +} +``` +{% include copy-curl.html %} + +In the response, note that the `population_data_knowledge_base` doesn't return the population of Seattle. Instead, the agent learns the population of Seattle by referencing historical messages: + +```json +{ + "inference_results": [ + { + "output": [ + { + "name": "memory_id", + "result": "LkJuyI0Bn3OCesyv3-Ef" + }, + { + "name": "parent_interaction_id", + "result": "00J6yI0Bn3OCesyvIuGZ" + }, + { + "name": "response", + "result": """{ + "thought": "Let me check the population data tool first", + "action": "population_data_knowledge_base", + "action_input": "{\"city\":\"Austin\",\"year\":2023}" +}""" + }, + { + "name": "response", + "result": """{"_index":"test_population_data","_source":{"population_description":"Chart and table of population level and growth rate for the Austin metro area from 1950 to 2023. United Nations population projections are also included through the year 2035.\\nThe current metro area population of Austin in 2023 is 2,228,000, a 2.39% increase from 2022.\\nThe metro area population of Austin in 2022 was 2,176,000, a 2.79% increase from 2021.\\nThe metro area population of Austin in 2021 was 2,117,000, a 3.12% increase from 2020.\\nThe metro area population of Austin in 2020 was 2,053,000, a 3.43% increase from 2019."},"_id":"BhF5vo0BubpYKX5ER0fT","_score":0.69129956} +{"_index":"test_population_data","_source":{"population_description":"Chart and table of population level and growth rate for the Austin metro area from 1950 to 2023. United Nations population projections are also included through the year 2035.\\nThe current metro area population of Austin in 2023 is 2,228,000, a 2.39% increase from 2022.\\nThe metro area population of Austin in 2022 was 2,176,000, a 2.79% increase from 2021.\\nThe metro area population of Austin in 2021 was 2,117,000, a 3.12% increase from 2020.\\nThe metro area population of Austin in 2020 was 2,053,000, a 3.43% increase from 2019."},"_id":"6zrZvo0BVR2NrurbRIAE","_score":0.69129956} +{"_index":"test_population_data","_source":{"population_description":"Chart and table of population level and growth rate for the New York City metro area from 1950 to 2023. United Nations population projections are also included through the year 2035.\\nThe current metro area population of New York City in 2023 is 18,937,000, a 0.37% increase from 2022.\\nThe metro area population of New York City in 2022 was 18,867,000, a 0.23% increase from 2021.\\nThe metro area population of New York City in 2021 was 18,823,000, a 0.1% increase from 2020.\\nThe metro area population of New York City in 2020 was 18,804,000, a 0.01% decline from 2019."},"_id":"AxF5vo0BubpYKX5ER0fT","_score":0.61015373} +""" + }, + { + "name": "response", + "result": "According to the population data tool, the population of Austin in 2023 is approximately 2,228,000 people, a 2.39% increase from 2022. This is lower than the population of Seattle in 2023 which is approximately 3,519,000 people, a 0.86% increase from 2022." + } + ] + } + ] +} +``` + +View all messages: + +```json +GET _plugins/_ml/memory/LkJuyI0Bn3OCesyv3-Ef/messages +``` +{% include copy-curl.html %} + +Obtain trace data: + +```json +GET _plugins/_ml/memory/message/00J6yI0Bn3OCesyvIuGZ/traces +``` +{% include copy-curl.html %} + +## Step 4 (Optional): Create an agent with a custom prompt + +All agents have the following default prompt: + +```json +"prompt": """ + +Human:${parameters.prompt.prefix} + +${parameters.prompt.suffix} + +Human: follow RESPONSE FORMAT INSTRUCTIONS + +Assistant:""" +``` + +The prompt consists of two parts: + +- `${parameters.prompt.prefix}`: A prompt prefix that describes what the AI assistant can do. You can change this parameter based on your use case, for example, `You are a professional data analyst. You will always answer questions based on the tool response first. If you don't know the answer, just say you don't know.` +- `${parameters.prompt.suffix}`: The main part of the prompt that defines the tools, chat history, prompt format instructions, a question, and a scratchpad. + +The default `prompt.suffix` is the following: + +```json +"prompt.suffix": """Human:TOOLS +------ +Assistant can ask Human to use tools to look up information that may be helpful in answering the users original question. The tool response will be listed in "TOOL RESPONSE of {tool name}:". If TOOL RESPONSE is enough to answer human's question, Assistant should avoid rerun the same tool. +Assistant should NEVER suggest run a tool with same input if it's already in TOOL RESPONSE. +The tools the human can use are: + +${parameters.tool_descriptions} + +${parameters.chat_history} + +${parameters.prompt.format_instruction} + + +Human:USER'S INPUT +-------------------- +Here is the user's input : +${parameters.question} + +${parameters.scratchpad}""" +``` + +The `prompt.suffix` consists of the following placeholders: + +- `${parameters.tool_descriptions}`: This placeholder will be filled with the agent's tool information: the tool name and description. If you omit this placeholder, the agent will not use any tools. +- `${parameters.prompt.format_instruction}`: This placeholder defines the LLM response format. This placeholder is critical, and we do not recommend removing it. +- `${parameters.chat_history}`: This placeholder will be filled with the message history of the current memory. If you don't set the `memory_id` when you run the agent, or if there are no history messages, then this placeholder will be empty. If you don't need chat history, you can remove this placeholder. +- `${parameters.question}`: This placeholder will be filled with the user question. +- `${parameters.scratchpad}`: This placeholder will be filled with the detailed agent execution steps. These steps are the same as those you can view by specifying verbose mode or obtaining trace data (see an example in [Test the agent](#test-the-agent)). This placeholder is critical in order for the LLM to reason and select the next step based on the outcome of the previous steps. We do not recommend removing this placeholder. + +### Custom prompt examples + +The following examples demonstrate how to customize the prompt. + +#### Example 1: Customize `prompt.prefix` + +Register an agent with a custom `prompt.prefix`: + +```json +POST _plugins/_ml/agents/_register +{ + "name": "Chat Agent with Custom Prompt", + "type": "conversational", + "description": "this is a test agent", + "app_type": "os_chat", + "llm": { + "model_id": "P0L8xI0Bn3OCesyvPsif", + "parameters": { + "max_iteration": 3, + "response_filter": "$.completion", + "prompt.prefix": "Assistant is a professional data analyst. You will always answer question based on the tool response first. If you don't know the answer, just say don't know.\n" + } + }, + "memory": { + "type": "conversation_index" + }, + "tools": [ + { + "type": "VectorDBTool", + "name": "population_data_knowledge_base", + "description": "This tool provide population data of US cities.", + "parameters": { + "input": "${parameters.question}", + "index": "test_population_data", + "source_field": [ + "population_description" + ], + "model_id": "xkJLyI0Bn3OCesyvf94S", + "embedding_field": "population_description_embedding", + "doc_size": 3 + } + }, + { + "type": "VectorDBTool", + "name": "stock_price_data_knowledge_base", + "description": "This tool provide stock price data.", + "parameters": { + "input": "${parameters.question}", + "index": "test_stock_price_data", + "source_field": [ + "stock_price_history" + ], + "model_id": "xkJLyI0Bn3OCesyvf94S", + "embedding_field": "stock_price_history_embedding", + "doc_size": 3 + } + } + ] +} +``` +{% include copy-curl.html %} + +Test the agent: + +```json +POST _plugins/_ml/agents/o0LDyI0Bn3OCesyvr-Zq/_execute +{ + "parameters": { + "question": "What's the stock price increase of Amazon from May 2023 to Feb 2023?", + "verbose": true + } +} +``` +{% include copy-curl.html %} + +#### Example 2: OpenAI model with a custom prompt + +Create a connector for the OpenAI `gpt-3.5-turbo` model: + +```json +POST _plugins/_ml/connectors/_create +{ + "name": "My openai connector: gpt-3.5-turbo", + "description": "The connector to openai chat model", + "version": 1, + "protocol": "http", + "parameters": { + "model": "gpt-3.5-turbo", + "response_filter": "$.choices[0].message.content", + "stop": ["\n\nHuman:","\nObservation:","\n\tObservation:","\n\tObservation","\n\nQuestion"], + "system_instruction": "You are an Assistant which can answer kinds of questions." + }, + "credential": { + "openAI_key": "your_openAI_key" + }, + "actions": [ + { + "action_type": "predict", + "method": "POST", + "url": "https://api.openai.com/v1/chat/completions", + "headers": { + "Authorization": "Bearer ${credential.openAI_key}" + }, + "request_body": "{ \"model\": \"${parameters.model}\", \"messages\": [{\"role\":\"system\",\"content\":\"${parameters.system_instruction}\"},{\"role\":\"user\",\"content\":\"${parameters.prompt}\"}] }" + } + ] +} +``` +{% include copy-curl.html %} + +Create a model using the connector ID from the response: + +```json +POST /_plugins/_ml/models/_register?deploy=true +{ + "name": "My OpenAI model", + "function_name": "remote", + "description": "test model", + "connector_id": "your_connector_id" +} +``` +{% include copy-curl.html %} + +Note the model ID and test the model by calling the Predict API: + +```json +POST /_plugins/_ml/models/your_openai_model_id/_predict +{ + "parameters": { + "system_instruction": "You are an Assistant which can answer kinds of questions.", + "prompt": "hello" + } +} +``` +{% include copy-curl.html %} + +Create an agent with a custom `system_instruction` and `prompt`. The `prompt` customizes the `tool_descriptions`, `chat_history`, `format_instruction`, `question`, and `scratchpad` placeholders: + +```json +POST _plugins/_ml/agents/_register +{ + "name": "My Chat Agent with OpenAI GPT 3.5", + "type": "conversational", + "description": "this is a test agent", + "app_type": "os_chat", + "llm": { + "model_id": "your_openai_model_id", + "parameters": { + "max_iteration": 3, + "response_filter": "$.choices[0].message.content", + "system_instruction": "You are an assistant which is designed to be able to assist with a wide range of tasks, from answering simple questions to providing in-depth explanations and discussions on a wide range of topics.", + "prompt": "Assistant can ask Human to use tools to look up information that may be helpful in answering the users original question.\n${parameters.tool_descriptions}\n\n${parameters.chat_history}\n\n${parameters.prompt.format_instruction}\n\nHuman: ${parameters.question}\n\n${parameters.scratchpad}\n\nHuman: follow RESPONSE FORMAT INSTRUCTIONS\n\nAssistant:", + "disable_trace": true + } + }, + "memory": { + "type": "conversation_index" + }, + "tools": [ + { + "type": "VectorDBTool", + "name": "population_data_knowledge_base", + "description": "This tool provide population data of US cities.", + "parameters": { + "input": "${parameters.question}", + "index": "test_population_data", + "source_field": [ + "population_description" + ], + "model_id": "your_embedding_model_id_from_step1", + "embedding_field": "population_description_embedding", + "doc_size": 3 + } + }, + { + "type": "VectorDBTool", + "name": "stock_price_data_knowledge_base", + "description": "This tool provide stock price data.", + "parameters": { + "input": "${parameters.question}", + "index": "test_stock_price_data", + "source_field": [ + "stock_price_history" + ], + "model_id": "your_embedding_model_id_from_step1", + "embedding_field": "stock_price_history_embedding", + "doc_size": 3 + } + } + ] +} +``` +{% include copy-curl.html %} + +Note the agent ID from the response and test the model by running the agent: + +```json +POST _plugins/_ml/agents/your_agent_id/_execute +{ + "parameters": { + "question": "What's the stock price increase of Amazon from May 2023 to Feb 2023?", + "verbose": true + } +} +``` +{% include copy-curl.html %} + +Test the agent by asking a question that requires the agent to use both configured tools: + +```json +POST _plugins/_ml/agents/your_agent_id/_execute +{ + "parameters": { + "question": "What's the population increase of Seattle from 2021 to 2023? Then check what's the stock price increase of Amazon from May 2023 to Feb 2023?", + "verbose": true + } +} +``` +{% include copy-curl.html %} + +The response shows that the agent runs both the `population_data_knowledge_base` and `stock_price_data_knowledge_base` tools to obtain the answer: + +```json +{ + "inference_results": [ + { + "output": [ + { + "name": "memory_id", + "result": "_0IByY0Bn3OCesyvJenb" + }, + { + "name": "parent_interaction_id", + "result": "AEIByY0Bn3OCesyvJerm" + }, + { + "name": "response", + "result": """{ + "thought": "I need to use a tool to find the population increase of Seattle from 2021 to 2023", + "action": "population_data_knowledge_base", + "action_input": "{\"city\": \"Seattle\", \"start_year\": 2021, \"end_year\": 2023}" +}""" + }, + { + "name": "response", + "result": """{"_index":"test_population_data","_source":{"population_description":"Chart and table of population level and growth rate for the Seattle metro area from 1950 to 2023. United Nations population projections are also included through the year 2035.\\nThe current metro area population of Seattle in 2023 is 3,519,000, a 0.86% increase from 2022.\\nThe metro area population of Seattle in 2022 was 3,489,000, a 0.81% increase from 2021.\\nThe metro area population of Seattle in 2021 was 3,461,000, a 0.82% increase from 2020.\\nThe metro area population of Seattle in 2020 was 3,433,000, a 0.79% increase from 2019."},"_id":"9EJsyI0Bn3OCesyvU-B7","_score":0.6542084} +{"_index":"test_population_data","_source":{"population_description":"Chart and table of population level and growth rate for the New York City metro area from 1950 to 2023. United Nations population projections are also included through the year 2035.\\nThe current metro area population of New York City in 2023 is 18,937,000, a 0.37% increase from 2022.\\nThe metro area population of New York City in 2022 was 18,867,000, a 0.23% increase from 2021.\\nThe metro area population of New York City in 2021 was 18,823,000, a 0.1% increase from 2020.\\nThe metro area population of New York City in 2020 was 18,804,000, a 0.01% decline from 2019."},"_id":"8EJsyI0Bn3OCesyvU-B7","_score":0.5966786} +{"_index":"test_population_data","_source":{"population_description":"Chart and table of population level and growth rate for the Austin metro area from 1950 to 2023. United Nations population projections are also included through the year 2035.\\nThe current metro area population of Austin in 2023 is 2,228,000, a 2.39% increase from 2022.\\nThe metro area population of Austin in 2022 was 2,176,000, a 2.79% increase from 2021.\\nThe metro area population of Austin in 2021 was 2,117,000, a 3.12% increase from 2020.\\nThe metro area population of Austin in 2020 was 2,053,000, a 3.43% increase from 2019."},"_id":"80JsyI0Bn3OCesyvU-B7","_score":0.5883104} +""" + }, + { + "name": "response", + "result": """{ + "thought": "I need to use a tool to find the stock price increase of Amazon from May 2023 to Feb 2023", + "action": "stock_price_data_knowledge_base", + "action_input": "{\"company\": \"Amazon\", \"start_date\": \"May 2023\", \"end_date\": \"Feb 2023\"}" +}""" + }, + { + "name": "response", + "result": """{"_index":"test_stock_price_data","_source":{"stock_price_history":"This is the historical montly stock price record for Amazon.com, Inc. (AMZN) with CSV format.\nDate,Open,High,Low,Close,Adj Close,Volume\n2023-03-01,93.870003,103.489998,88.120003,103.290001,103.290001,1349240300\n2023-04-01,102.300003,110.860001,97.709999,105.449997,105.449997,1224083600\n2023-05-01,104.949997,122.919998,101.150002,120.580002,120.580002,1432891600\n2023-06-01,120.690002,131.490005,119.930000,130.360001,130.360001,1242648800\n2023-07-01,130.820007,136.649994,125.919998,133.679993,133.679993,1058754800\n2023-08-01,133.550003,143.630005,126.410004,138.009995,138.009995,1210426200\n2023-09-01,139.460007,145.860001,123.040001,127.120003,127.120003,1120271900\n2023-10-01,127.279999,134.479996,118.349998,133.089996,133.089996,1224564700\n2023-11-01,133.960007,149.259995,133.710007,146.089996,146.089996,1025986900\n2023-12-01,146.000000,155.630005,142.809998,151.940002,151.940002,931128600\n2024-01-01,151.539993,161.729996,144.050003,155.199997,155.199997,953344900\n2024-02-01,155.869995,175.000000,155.619995,174.449997,174.449997,437720800\n"},"_id":"BUJsyI0Bn3OCesyvveHo","_score":0.63949186} +{"_index":"test_stock_price_data","_source":{"stock_price_history":"This is the historical montly stock price record for Alphabet Inc. (GOOG) with CSV format.\n\nDate,Open,High,Low,Close,Adj Close,Volume\n2023-03-01,90.160004,107.510002,89.769997,104.000000,104.000000,725477100\n2023-04-01,102.669998,109.629997,102.379997,108.220001,108.220001,461670700\n2023-05-01,107.720001,127.050003,104.500000,123.370003,123.370003,620317400\n2023-06-01,123.500000,129.550003,116.910004,120.970001,120.970001,521386300\n2023-07-01,120.320000,134.070007,115.830002,133.110001,133.110001,525456900\n2023-08-01,130.854996,138.399994,127.000000,137.350006,137.350006,463482000\n2023-09-01,138.429993,139.929993,128.190002,131.850006,131.850006,389593900\n2023-10-01,132.154999,142.380005,121.459999,125.300003,125.300003,514877100\n2023-11-01,125.339996,141.100006,124.925003,133.919998,133.919998,405635900\n2023-12-01,133.320007,143.945007,129.399994,140.929993,140.929993,482059400\n2024-01-01,139.600006,155.199997,136.850006,141.800003,141.800003,428771200\n2024-02-01,143.690002,150.695007,138.169998,147.139999,147.139999,231934100\n"},"_id":"CkJsyI0Bn3OCesyvveHo","_score":0.6056718} +{"_index":"test_stock_price_data","_source":{"stock_price_history":"This is the historical montly stock price record for Apple Inc. (AAPL) with CSV format.\nDate,Open,High,Low,Close,Adj Close,Volume\n2023-03-01,146.830002,165.000000,143.899994,164.899994,164.024475,1520266600\n2023-04-01,164.270004,169.850006,159.779999,169.679993,168.779099,969709700\n2023-05-01,169.279999,179.350006,164.309998,177.250000,176.308914,1275155500\n2023-06-01,177.699997,194.479996,176.929993,193.970001,193.207016,1297101100\n2023-07-01,193.779999,198.229996,186.600006,196.449997,195.677261,996066400\n2023-08-01,196.240005,196.729996,171.960007,187.869995,187.130997,1322439400\n2023-09-01,189.490005,189.979996,167.619995,171.210007,170.766846,1337586600\n2023-10-01,171.220001,182.339996,165.669998,170.770004,170.327972,1172719600\n2023-11-01,171.000000,192.929993,170.119995,189.949997,189.458313,1099586100\n2023-12-01,190.330002,199.619995,187.449997,192.529999,192.284637,1062774800\n2024-01-01,187.149994,196.380005,180.169998,184.399994,184.164993,1187219300\n2024-02-01,183.990005,191.050003,179.250000,188.850006,188.609329,420063900\n"},"_id":"BkJsyI0Bn3OCesyvveHo","_score":0.5960163} +""" + }, + { + "name": "response", + "result": "The population increase of Seattle from 2021 to 2023 is 0.86%. The stock price increase of Amazon from May 2023 to Feb 2023 is from $120.58 to $174.45, which is a percentage increase." + } + ] + } + ] +} +``` + +## Step 5: Configure a root chatbot agent in OpenSearch Dashboards + +To use the [OpenSearch Assistant for OpenSearch Dashboards]({{site.url}}{{site.baseurl}}/dashboards/dashboards-assistant/index/), you need to configure a root chatbot agent. + +A root chatbot agent consists of the following parts: + +- A `conversational` agent: Within the `AgentTool`, you can use any `conversational` agent created in the previous steps. +- An `MLModelTool`: This tool is used for suggesting new questions based on your current question and the model response. + +Configure a root agent: + +```json +POST /_plugins/_ml/agents/_register +{ + "name": "Chatbot agent", + "type": "flow", + "description": "this is a test chatbot agent", + "tools": [ + { + "type": "AgentTool", + "name": "LLMResponseGenerator", + "parameters": { + "agent_id": "your_conversational_agent_created_in_prevous_steps" + }, + "include_output_in_agent_response": true + }, + { + "type": "MLModelTool", + "name": "QuestionSuggestor", + "description": "A general tool to answer any question", + "parameters": { + "model_id": "your_llm_model_id_created_in_previous_steps", + "prompt": "Human: You are an AI that only speaks JSON. Do not write normal text. Output should follow example JSON format: \n\n {\"response\": [\"question1\", \"question2\"]}\n\n. \n\nHuman:You will be given a chat history between OpenSearch Assistant and a Human.\nUse the context provided to generate follow up questions the Human would ask to the Assistant.\nThe Assistant can answer general questions about logs, traces and metrics.\nAssistant can access a set of tools listed below to answer questions given by the Human:\nQuestion suggestions generator tool\nHere's the chat history between the human and the Assistant.\n${parameters.LLMResponseGenerator.output}\nUse the following steps to generate follow up questions Human may ask after the response of the Assistant:\nStep 1. Use the chat history to understand what human is trying to search and explore.\nStep 2. Understand what capabilities the assistant has with the set of tools it has access to.\nStep 3. Use the above context and generate follow up questions.Step4:You are an AI that only speaks JSON. Do not write normal text. Output should follow example JSON format: \n\n {\"response\": [\"question1\", \"question2\"]} \n \n----------------\n\nAssistant:" + }, + "include_output_in_agent_response": true + } + ], + "memory": { + "type": "conversation_index" + } +} +``` +{% include copy-curl.html %} + +Note the root chatbot agent ID, log in to your OpenSearch server, go to the OpenSearch config folder (`$OS_HOME/config`), and run the following command: + +```bashx + curl -k --cert ./kirk.pem --key ./kirk-key.pem -X PUT https://localhost:9200/.plugins-ml-config/_doc/os_chat -H 'Content-Type: application/json' -d' + { + "type":"os_chat_root_agent", + "configuration":{ + "agent_id": "your_root_chatbot_agent_id" + } + }' +``` +{% include copy.html %} + +Go to your OpenSearch Dashboards config folder (`$OSD_HOME/config`) and edit `opensearch_dashboards.yml` by adding the following line to the end of the file: `assistant.chat.enabled: true`. + +Restart OpenSearch Dashboards and then select the chat icon in the upper-right corner, shown in the following image. + +OpenSearch Assistant icon + +You can now chat in OpenSearch Dashboards, as shown in the following image. + +OpenSearch Assistant chat \ No newline at end of file diff --git a/_ml-commons-plugin/tutorials/conversational-search-cohere.md b/_ml-commons-plugin/tutorials/conversational-search-cohere.md new file mode 100644 index 0000000000..e02f576b7c --- /dev/null +++ b/_ml-commons-plugin/tutorials/conversational-search-cohere.md @@ -0,0 +1,228 @@ +--- +layout: default +title: Conversational search with Cohere Command +parent: Tutorials +nav_order: 20 +--- + +# Conversational search using the Cohere Command model + +This tutorial illustrates how to configure conversational search using the Cohere Command model. For more information, see [Conversational search]({{site.url}}{{site.baseurl}}/search-plugins/conversational-search/). + +Replace the placeholders beginning with the prefix `your_` with your own values. +{: .note} + +Alternatively, you can build a RAG/conversational search using agents and tools. For more information, see [Retrieval-augmented generation chatbot]({{site.url}}{{site.baseurl}}/ml-commons-plugin/tutorials/rag-conversational-agent/). + +## Prerequisite + +Ingest test data: + +```json +POST _bulk +{"index": {"_index": "qa_demo", "_id": "1"}} +{"text": "Chart and table of population level and growth rate for the Ogden-Layton metro area from 1950 to 2023. United Nations population projections are also included through the year 2035.\nThe current metro area population of Ogden-Layton in 2023 is 750,000, a 1.63% increase from 2022.\nThe metro area population of Ogden-Layton in 2022 was 738,000, a 1.79% increase from 2021.\nThe metro area population of Ogden-Layton in 2021 was 725,000, a 1.97% increase from 2020.\nThe metro area population of Ogden-Layton in 2020 was 711,000, a 2.16% increase from 2019."} +{"index": {"_index": "qa_demo", "_id": "2"}} +{"text": "Chart and table of population level and growth rate for the New York City metro area from 1950 to 2023. United Nations population projections are also included through the year 2035.\\nThe current metro area population of New York City in 2023 is 18,937,000, a 0.37% increase from 2022.\\nThe metro area population of New York City in 2022 was 18,867,000, a 0.23% increase from 2021.\\nThe metro area population of New York City in 2021 was 18,823,000, a 0.1% increase from 2020.\\nThe metro area population of New York City in 2020 was 18,804,000, a 0.01% decline from 2019."} +{"index": {"_index": "qa_demo", "_id": "3"}} +{"text": "Chart and table of population level and growth rate for the Chicago metro area from 1950 to 2023. United Nations population projections are also included through the year 2035.\\nThe current metro area population of Chicago in 2023 is 8,937,000, a 0.4% increase from 2022.\\nThe metro area population of Chicago in 2022 was 8,901,000, a 0.27% increase from 2021.\\nThe metro area population of Chicago in 2021 was 8,877,000, a 0.14% increase from 2020.\\nThe metro area population of Chicago in 2020 was 8,865,000, a 0.03% increase from 2019."} +{"index": {"_index": "qa_demo", "_id": "4"}} +{"text": "Chart and table of population level and growth rate for the Miami metro area from 1950 to 2023. United Nations population projections are also included through the year 2035.\\nThe current metro area population of Miami in 2023 is 6,265,000, a 0.8% increase from 2022.\\nThe metro area population of Miami in 2022 was 6,215,000, a 0.78% increase from 2021.\\nThe metro area population of Miami in 2021 was 6,167,000, a 0.74% increase from 2020.\\nThe metro area population of Miami in 2020 was 6,122,000, a 0.71% increase from 2019."} +{"index": {"_index": "qa_demo", "_id": "5"}} +{"text": "Chart and table of population level and growth rate for the Austin metro area from 1950 to 2023. United Nations population projections are also included through the year 2035.\\nThe current metro area population of Austin in 2023 is 2,228,000, a 2.39% increase from 2022.\\nThe metro area population of Austin in 2022 was 2,176,000, a 2.79% increase from 2021.\\nThe metro area population of Austin in 2021 was 2,117,000, a 3.12% increase from 2020.\\nThe metro area population of Austin in 2020 was 2,053,000, a 3.43% increase from 2019."} +{"index": {"_index": "qa_demo", "_id": "6"}} +{"text": "Chart and table of population level and growth rate for the Seattle metro area from 1950 to 2023. United Nations population projections are also included through the year 2035.\\nThe current metro area population of Seattle in 2023 is 3,519,000, a 0.86% increase from 2022.\\nThe metro area population of Seattle in 2022 was 3,489,000, a 0.81% increase from 2021.\\nThe metro area population of Seattle in 2021 was 3,461,000, a 0.82% increase from 2020.\\nThe metro area population of Seattle in 2020 was 3,433,000, a 0.79% increase from 2019."} +``` +{% include copy-curl.html %} + +## Step 1: Create a connector and register a model + +Conversational search only supports the [OpenAI](https://github.com/opensearch-project/ml-commons/blob/2.x/docs/remote_inference_blueprints/open_ai_connector_chat_blueprint.md) +and [Amazon Bedrock Claude](https://github.com/opensearch-project/ml-commons/blob/2.x/docs/remote_inference_blueprints/bedrock_connector_anthropic_claude_blueprint.md) input/output styles. +{: .important} + +This tutorial follows the Amazon Bedrock Claude model input/output style by: +- Mapping the Cohere Command `message` input parameter to the `inputs` parameter in order to match the Cohere Claude model input style. +- Using a post-processing function to convert the Cohere Command model output to the Claude model output style. + +Create a connector for the Cohere Command model: + +```json +POST _plugins/_ml/connectors/_create +{ + "name": "Cohere Chat Model", + "description": "The connector to Cohere's public chat API", + "version": "1", + "protocol": "http", + "credential": { + "cohere_key": "your_cohere_api_key" + }, + "parameters": { + "model": "command" + }, + "actions": [ + { + "action_type": "predict", + "method": "POST", + "url": "https://api.cohere.ai/v1/chat", + "headers": { + "Authorization": "Bearer ${credential.cohere_key}", + "Request-Source": "unspecified:opensearch" + }, + "request_body": "{ \"message\": \"${parameters.inputs}\", \"model\": \"${parameters.model}\" }", + "post_process_function": "\n String escape(def input) { \n if (input.contains(\"\\\\\")) {\n input = input.replace(\"\\\\\", \"\\\\\\\\\");\n }\n if (input.contains(\"\\\"\")) {\n input = input.replace(\"\\\"\", \"\\\\\\\"\");\n }\n if (input.contains('\r')) {\n input = input = input.replace('\r', '\\\\r');\n }\n if (input.contains(\"\\\\t\")) {\n input = input.replace(\"\\\\t\", \"\\\\\\\\\\\\t\");\n }\n if (input.contains('\n')) {\n input = input.replace('\n', '\\\\n');\n }\n if (input.contains('\b')) {\n input = input.replace('\b', '\\\\b');\n }\n if (input.contains('\f')) {\n input = input.replace('\f', '\\\\f');\n }\n return input;\n }\n def name = 'response';\n def result = params.text;\n def json = '{ \"name\": \"' + name + '\",' +\n '\"dataAsMap\": { \"completion\": \"' + escape(result) +\n '\"}}';\n return json;\n \n " + } + ] +} +``` +{% include copy-curl.html %} + +Starting in OpenSearch 2.12, you can use the default `escape` function directly in the `post_process_function`: + +```json +"post_process_function": " \n def name = 'response';\n def result = params.text;\n def json = '{ \"name\": \"' + name + '\",' +\n '\"dataAsMap\": { \"completion\": \"' + escape(result) +\n '\"}}';\n return json;" +``` +{% include copy-curl.html %} + +Note the connector ID; you'll use it to register the model. + +Register the Cohere Command model: + +```json +POST /_plugins/_ml/models/_register?deploy=true +{ + "name": "Cohere command model", + "function_name": "remote", + "description": "Cohere command model", + "connector_id": "your_connector_id" +} +``` +{% include copy-curl.html %} + +Note the model ID; you'll use it in the following steps. + +Test the model: + +```json +POST /_plugins/_ml/models/your_model_id/_predict +{ + "parameters": { + "inputs": "What is the weather like in Seattle?" + } +} +``` +{% include copy-curl.html %} + +The response contains the LLM completion: + +```json +{ + "inference_results": [ + { + "output": [ + { + "name": "response", + "dataAsMap": { + "completion": """It is difficult to provide a comprehensive answer without a specific location or time frame in mind. + +As an AI language model, I have no access to real-time data or the ability to provide live weather reports. Instead, I can offer some general information about Seattle's weather, which is known for its mild, wet climate. + +Located in the Pacific Northwest region of the United States, Seattle experiences a maritime climate with cool, dry summers and mild, wet winters. While it is best known for its rainy days, Seattle's annual rainfall is actually less than New York City and Boston. + +Would you like me to provide more details on Seattle's weather? Or, if you have a specific date or location in mind, I can try to retrieve real-time or historical weather information for you.""" + } + } + ], + "status_code": 200 + } + ] +} +``` + +## Step 2: Configure conversational search + +Create a search pipeline containing a RAG processor: + +```json +PUT /_search/pipeline/my-conversation-search-pipeline-cohere +{ + "response_processors": [ + { + "retrieval_augmented_generation": { + "tag": "Demo pipeline", + "description": "Demo pipeline Using Cohere", + "model_id": "your_model_id_created_in_step1", + "context_field_list": [ + "text" + ], + "system_prompt": "You are a helpful assistant", + "user_instructions": "Generate a concise and informative answer in less than 100 words for the given question" + } + } + ] +} +``` +{% include copy-curl.html %} + +To run a conversational search, specify its parameters in the `generative_qa_parameters` object: + +```json +GET /qa_demo/_search?search_pipeline=my-conversation-search-pipeline-cohere +{ + "query": { + "match": { + "text": "What's the population increase of New York City from 2021 to 2023?" + } + }, + "size": 1, + "_source": [ + "text" + ], + "ext": { + "generative_qa_parameters": { + "llm_model": "bedrock/claude", + "llm_question": "What's the population increase of New York City from 2021 to 2023?", + "context_size": 5, + "timeout": 15 + } + } +} +``` +{% include copy-curl.html %} + +The response contains the model's answer: + +```json +{ + "took": 1, + "timed_out": false, + "_shards": { + "total": 1, + "successful": 1, + "skipped": 0, + "failed": 0 + }, + "hits": { + "total": { + "value": 6, + "relation": "eq" + }, + "max_score": 9.042081, + "hits": [ + { + "_index": "qa_demo", + "_id": "2", + "_score": 9.042081, + "_source": { + "text": """Chart and table of population level and growth rate for the New York City metro area from 1950 to 2023. United Nations population projections are also included through the year 2035.\nThe current metro area population of New York City in 2023 is 18,937,000, a 0.37% increase from 2022.\nThe metro area population of New York City in 2022 was 18,867,000, a 0.23% increase from 2021.\nThe metro area population of New York City in 2021 was 18,823,000, a 0.1% increase from 2020.\nThe metro area population of New York City in 2020 was 18,804,000, a 0.01% decline from 2019.""" + } + } + ] + }, + "ext": { + "retrieval_augmented_generation": { + "answer": "The population of the New York City metro area increased by about 210,000 from 2021 to 2023. The 2021 population was 18,823,000, and in 2023 it was 18,937,000. The average growth rate is 0.23% yearly." + } + } +} +``` \ No newline at end of file diff --git a/_ml-commons-plugin/tutorials/generate-embeddings.md b/_ml-commons-plugin/tutorials/generate-embeddings.md new file mode 100644 index 0000000000..92b62b9fe8 --- /dev/null +++ b/_ml-commons-plugin/tutorials/generate-embeddings.md @@ -0,0 +1,336 @@ +--- +layout: default +title: Generating embeddings +parent: Tutorials +nav_order: 5 +--- + +# Generating embeddings for arrays of objects + +This tutorial illustrates how to generate embeddings for arrays of objects. + +Replace the placeholders beginning with the prefix `your_` with your own values. +{: .note} + +## Step 1: Register an embedding model + +For this tutorial, you will use the [Amazon Bedrock Titan Embedding model](https://docs.aws.amazon.com/bedrock/latest/userguide/titan-embedding-models.html). + +First, follow the [Amazon Bedrock Titan blueprint example](https://github.com/opensearch-project/ml-commons/blob/2.x/docs/remote_inference_blueprints/bedrock_connector_titan_embedding_blueprint.md) to register and deploy the model. + +Test the model, providing the model ID: + +```json +POST /_plugins/_ml/models/your_embedding_model_id/_predict +{ + "parameters": { + "inputText": "hello world" + } +} +``` +{% include copy-curl.html %} + +The response contains inference results: + +```json +{ + "inference_results": [ + { + "output": [ + { + "name": "sentence_embedding", + "data_type": "FLOAT32", + "shape": [ 1536 ], + "data": [0.7265625, -0.0703125, 0.34765625, ...] + } + ], + "status_code": 200 + } + ] +} +``` + +## Step 2: Create an ingest pipeline + +Follow the next set of steps to create an ingest pipeline for generating embeddings. + +### Step 2.1: Create a k-NN index + +First, create a k-NN index: + +```json +PUT my_books +{ + "settings" : { + "index.knn" : "true", + "default_pipeline": "bedrock_embedding_foreach_pipeline" + }, + "mappings": { + "properties": { + "books": { + "type": "nested", + "properties": { + "title_embedding": { + "type": "knn_vector", + "dimension": 1536 + }, + "title": { + "type": "text" + }, + "description": { + "type": "text" + } + } + } + } + } +} +``` +{% include copy-curl.html %} + +### Step 2.2: Create an ingest pipeline + +Then create an inner ingest pipeline to generate an embedding for one array element. + +This pipeline contains three processors: + +- `set` processor: The `text_embedding` processor is unable to identify the `_ingest._value.title` field. You must copy `_ingest._value.title` to a non-existing temporary field so that the `text_embedding` processor can process it. +- `text_embedding` processor: Converts the value of the temporary field to an embedding. +- `remove` processor: Removes the temporary field. + +To create such a pipeline, send the following request: + +```json +PUT _ingest/pipeline/bedrock_embedding_pipeline +{ + "processors": [ + { + "set": { + "field": "title_tmp", + "value": "{{_ingest._value.title}}" + } + }, + { + "text_embedding": { + "model_id": your_embedding_model_id, + "field_map": { + "title_tmp": "_ingest._value.title_embedding" + } + } + }, + { + "remove": { + "field": "title_tmp" + } + } + ] +} +``` +{% include copy-curl.html %} + +Create an ingest pipeline with a `foreach` processor that will apply the `bedrock_embedding_pipeline` to each element of the `books` array: + +```json +PUT _ingest/pipeline/bedrock_embedding_foreach_pipeline +{ + "description": "Test nested embeddings", + "processors": [ + { + "foreach": { + "field": "books", + "processor": { + "pipeline": { + "name": "bedrock_embedding_pipeline" + } + }, + "ignore_failure": true + } + } + ] +} +``` +{% include copy-curl.html %} + +### Step 2.3: Simulate the pipeline + +First, you'll test the pipeline on an array that contains two book objects, both with a `title` field: + +```json +POST _ingest/pipeline/bedrock_embedding_foreach_pipeline/_simulate +{ + "docs": [ + { + "_index": "my_books", + "_id": "1", + "_source": { + "books": [ + { + "title": "first book", + "description": "This is first book" + }, + { + "title": "second book", + "description": "This is second book" + } + ] + } + } + ] +} +``` +{% include copy-curl.html %} + +The response contains generated embeddings for both objects in their `title_embedding` fields: + +```json +{ + "docs": [ + { + "doc": { + "_index": "my_books", + "_id": "1", + "_source": { + "books": [ + { + "title": "first book", + "title_embedding": [-1.1015625, 0.65234375, 0.7578125, ...], + "description": "This is first book" + }, + { + "title": "second book", + "title_embedding": [-0.65234375, 0.21679688, 0.7265625, ...], + "description": "This is second book" + } + ] + }, + "_ingest": { + "_value": null, + "timestamp": "2024-05-28T16:16:50.538929413Z" + } + } + } + ] +} +``` + +Next, you'll test the pipeline on an array that contains two book objects, one with a `title` field and one without: + +```json +POST _ingest/pipeline/bedrock_embedding_foreach_pipeline/_simulate +{ + "docs": [ + { + "_index": "my_books", + "_id": "1", + "_source": { + "books": [ + { + "title": "first book", + "description": "This is first book" + }, + { + "description": "This is second book" + } + ] + } + } + ] +} +``` +{% include copy-curl.html %} + +The response contains generated embeddings for the object that contains the `title` field: + +```json +{ + "docs": [ + { + "doc": { + "_index": "my_books", + "_id": "1", + "_source": { + "books": [ + { + "title": "first book", + "title_embedding": [-1.1015625, 0.65234375, 0.7578125, ...], + "description": "This is first book" + }, + { + "description": "This is second book" + } + ] + }, + "_ingest": { + "_value": null, + "timestamp": "2024-05-28T16:19:03.942644042Z" + } + } + } + ] +} +``` +### Step 2.4: Test data ingestion + +Ingest one document: + +```json +PUT my_books/_doc/1 +{ + "books": [ + { + "title": "first book", + "description": "This is first book" + }, + { + "title": "second book", + "description": "This is second book" + } + ] +} +``` +{% include copy-curl.html %} + +Get the document: + +```json +GET my_books/_doc/1 +``` +{% include copy-curl.html %} + +The response contains the generated embeddings: + +```json +{ + "_index": "my_books", + "_id": "1", + "_version": 1, + "_seq_no": 0, + "_primary_term": 1, + "found": true, + "_source": { + "books": [ + { + "description": "This is first book", + "title": "first book", + "title_embedding": [-1.1015625, 0.65234375, 0.7578125, ...] + }, + { + "description": "This is second book", + "title": "second book", + "title_embedding": [-0.65234375, 0.21679688, 0.7265625, ...] + } + ] + } +} +``` + +You can also ingest several documents in bulk and test the generated embeddings by calling the Get Document API: + +```json +POST _bulk +{ "index" : { "_index" : "my_books" } } +{ "books" : [{"title": "first book", "description": "This is first book"}, {"title": "second book", "description": "This is second book"}] } +{ "index" : { "_index" : "my_books" } } +{ "books" : [{"title": "third book", "description": "This is third book"}, {"description": "This is fourth book"}] } +``` +{% include copy-curl.html %} \ No newline at end of file diff --git a/_ml-commons-plugin/tutorials/index.md b/_ml-commons-plugin/tutorials/index.md new file mode 100644 index 0000000000..4479d0878f --- /dev/null +++ b/_ml-commons-plugin/tutorials/index.md @@ -0,0 +1,26 @@ +--- +layout: default +title: Tutorials +has_children: true +has_toc: false +nav_order: 140 +--- + +# Tutorials + +Using the OpenSearch machine learning (ML) framework, you can build various applications, from implementing conversational search to building your own chatbot. To learn more, explore the following ML tutorials: + +- **Semantic search**: + - [Generating embeddings for arrays of objects]({{site.url}}{{site.baseurl}}/ml-commons-plugin/tutorials/generate-embeddings/) + - [Semantic search using byte-quantized vectors]({{site.url}}{{site.baseurl}}/ml-commons-plugin/tutorials/semantic-search-byte-vectors/) + +- **Conversational search**: + - [Conversational search using the Cohere Command model]({{site.url}}{{site.baseurl}}/ml-commons-plugin/tutorials/conversational-search-cohere/) + +- **Reranking search results**: + - [Reranking search results using the Cohere Rerank model]({{site.url}}{{site.baseurl}}/ml-commons-plugin/tutorials/reranking-cohere/) + +- **Agents and tools**: + - [Retrieval-augmented generation (RAG) chatbot]({{site.url}}{{site.baseurl}}/ml-commons-plugin/tutorials/rag-chatbot/) + - [RAG with a conversational flow agent]({{site.url}}{{site.baseurl}}/ml-commons-plugin/tutorials/rag-conversational-agent/) + - [Build your own chatbot]({{site.url}}{{site.baseurl}}/ml-commons-plugin/tutorials/build-chatbot/) \ No newline at end of file diff --git a/_ml-commons-plugin/tutorials/rag-chatbot.md b/_ml-commons-plugin/tutorials/rag-chatbot.md new file mode 100644 index 0000000000..5dddded23a --- /dev/null +++ b/_ml-commons-plugin/tutorials/rag-chatbot.md @@ -0,0 +1,346 @@ +--- +layout: default +title: RAG chatbot +parent: Tutorials +nav_order: 50 +--- + +# RAG chatbot + +One of the known limitations of large language models (LLMs) is that their knowledge base only contains information from the period of time during which they were trained. LLMs have no knowledge of recent events or of your internal data. You can augment the LLM knowledge base by using retrieval-augmented generation (RAG). + +This tutorial illustrates how to build your own chatbot using [agents and tools](https://opensearch.org/docs/latest/ml-commons-plugin/agents-tools/index/) and RAG. RAG supplements the LLM knowledge base with information contained in OpenSearch indexes. + +Replace the placeholders beginning with the prefix `your_` with your own values. +{: .note} + +## Prerequisite + +Meet the prerequisite and follow Step 1 of the [RAG with a conversational flow agent tutorial]({{site.url}}{{site.baseurl}}/ml-commons-plugin/tutorials/rag-conversational-agent/) to set up the `test_population_data` knowledge base index, which contains US city population data. + +Note the embedding model ID; you'll use it in the following steps. + +## Step 1: Set up a knowledge base + +First, create an ingest pipeline: + +```json +PUT /_ingest/pipeline/test_tech_news_pipeline +{ + "description": "text embedding pipeline for tech news", + "processors": [ + { + "text_embedding": { + "model_id": "your_text_embedding_model_id", + "field_map": { + "passage": "passage_embedding" + } + } + } + ] +} +``` +{% include copy-curl.html %} + +Next, create an index named `test_tech_news`, which contains recent tech news: + +```json +PUT test_tech_news +{ + "mappings": { + "properties": { + "passage": { + "type": "text" + }, + "passage_embedding": { + "type": "knn_vector", + "dimension": 384 + } + } + }, + "settings": { + "index": { + "knn.space_type": "cosinesimil", + "default_pipeline": "test_tech_news_pipeline", + "knn": "true" + } + } +} +``` +{% include copy-curl.html %} + +Ingest data into the index: + +```json +POST _bulk +{"index":{"_index":"test_tech_news"}} +{"c":"Apple Vision Pro is a mixed-reality headset developed by Apple Inc. It was announced on June 5, 2023, at Apple's Worldwide Developers Conference, and pre-orders began on January 19, 2024. It became available for purchase on February 2, 2024, in the United States.[10] A worldwide launch has yet to be scheduled. The Vision Pro is Apple's first new major product category since the release of the Apple Watch in 2015.[11]\n\nApple markets the Vision Pro as a \"spatial computer\" where digital media is integrated with the real world. Physical inputs—such as motion gestures, eye tracking, and speech recognition—can be used to interact with the system.[10] Apple has avoided marketing the device as a virtual reality headset, along with the use of the terms \"virtual reality\" and \"augmented reality\" when discussing the product in presentations and marketing.[12]\n\nThe device runs visionOS,[13] a mixed-reality operating system derived from iOS frameworks using a 3D user interface; it supports multitasking via windows that appear to float within the user's surroundings,[14] as seen by cameras built into the headset. A dial on the top of the headset can be used to mask the camera feed with a virtual environment to increase immersion. The OS supports avatars (officially called \"Personas\"), which are generated by scanning the user's face; a screen on the front of the headset displays a rendering of the avatar's eyes (\"EyeSight\"), which are used to indicate the user's level of immersion to bystanders, and assist in communication.[15]"} +{"index":{"_index":"test_tech_news"}} +{"passage":"LLaMA (Large Language Model Meta AI) is a family of autoregressive large language models (LLMs), released by Meta AI starting in February 2023.\n\nFor the first version of LLaMA, four model sizes were trained: 7, 13, 33, and 65 billion parameters. LLaMA's developers reported that the 13B parameter model's performance on most NLP benchmarks exceeded that of the much larger GPT-3 (with 175B parameters) and that the largest model was competitive with state of the art models such as PaLM and Chinchilla.[1] Whereas the most powerful LLMs have generally been accessible only through limited APIs (if at all), Meta released LLaMA's model weights to the research community under a noncommercial license.[2] Within a week of LLaMA's release, its weights were leaked to the public on 4chan via BitTorrent.[3]\n\nIn July 2023, Meta released several models as Llama 2, using 7, 13 and 70 billion parameters.\n\nLLaMA-2\n\nOn July 18, 2023, in partnership with Microsoft, Meta announced LLaMA-2, the next generation of LLaMA. Meta trained and released LLaMA-2 in three model sizes: 7, 13, and 70 billion parameters.[4] The model architecture remains largely unchanged from that of LLaMA-1 models, but 40% more data was used to train the foundational models.[5] The accompanying preprint[5] also mentions a model with 34B parameters that might be released in the future upon satisfying safety targets.\n\nLLaMA-2 includes both foundational models and models fine-tuned for dialog, called LLaMA-2 Chat. In further departure from LLaMA-1, all models are released with weights, and are free for many commercial use cases. However, due to some remaining restrictions, the description of LLaMA as open source has been disputed by the Open Source Initiative (known for maintaining the Open Source Definition).[6]\n\nIn November 2023, research conducted by Patronus AI, an artificial intelligence startup company, compared performance of LLaMA-2, OpenAI's GPT-4 and GPT-4-Turbo, and Anthropic's Claude2 on two versions of a 150-question test about information in SEC filings (e.g. Form 10-K, Form 10-Q, Form 8-K, earnings reports, earnings call transcripts) submitted by public companies to the agency where one version of the test required the generative AI models to use a retrieval system to locate the specific SEC filing to answer the questions while the other version provided the specific SEC filing to the models to answer the question (i.e. in a long context window). On the retrieval system version, GPT-4-Turbo and LLaMA-2 both failed to produce correct answers to 81% of the questions, while on the long context window version, GPT-4-Turbo and Claude-2 failed to produce correct answers to 21% and 24% of the questions respectively.[7][8]"} +{"index":{"_index":"test_tech_news"}} +{"passage":"Amazon Bedrock is a fully managed service that offers a choice of high-performing foundation models (FMs) from leading AI companies like AI21 Labs, Anthropic, Cohere, Meta, Stability AI, and Amazon via a single API, along with a broad set of capabilities you need to build generative AI applications with security, privacy, and responsible AI. Using Amazon Bedrock, you can easily experiment with and evaluate top FMs for your use case, privately customize them with your data using techniques such as fine-tuning and Retrieval Augmented Generation (RAG), and build agents that execute tasks using your enterprise systems and data sources. Since Amazon Bedrock is serverless, you don't have to manage any infrastructure, and you can securely integrate and deploy generative AI capabilities into your applications using the AWS services you are already familiar with."} +``` +{% include copy-curl.html %} + +## Step 2: Prepare an LLM + +Follow [step 2 of the RAG with a conversational flow agent tutorial]({{site.url}}{{site.baseurl}}/ml-commons-plugin/tutorials/rag-conversational-agent/#step-2-prepare-an-llm) to configure the Amazon Bedrock Claude model. + +Note the model ID; you'll use it in the following steps. + +## Step 3: Create an agent + +For this tutorial, you will create an agent of the `conversational` type. + +Both the `conversational_flow` and `conversational` agents support conversation history. + +The `conversational_flow` and `conversational` agents differ in the following ways: + +- A `conversational_flow` agent runs tools sequentially, in a predefined order. +- A `conversational` agent dynamically chooses which tool to run next. + +In this tutorial, the agent includes two tools: One provides recent population data, and the other contains tech news. + +The agent has the following parameters: + +- `"max_iteration": 5`: The agent runs the LLM a maximum of five times. +- `"response_filter": "$.completion"`: Needed to retrieve the LLM answer from the Amazon Bedrock Claude model response. +- `"doc_size": 3` (in `population_data_knowledge_base`): Specifies to return the top three documents. + +Create an agent with the preceding specifications: + +```json +POST _plugins/_ml/agents/_register +{ + "name": "Chat Agent with RAG", + "type": "conversational", + "description": "this is a test agent", + "llm": { + "model_id": "your_llm_model_id", + "parameters": { + "max_iteration": 5, + "response_filter": "$.completion" + } + }, + "memory": { + "type": "conversation_index" + }, + "tools": [ + { + "type": "VectorDBTool", + "name": "population_data_knowledge_base", + "description": "This tool provides population data of US cities.", + "parameters": { + "input": "${parameters.question}", + "index": "test_population_data", + "source_field": [ + "population_description" + ], + "model_id": "your_text_embedding_model_id", + "embedding_field": "population_description_embedding", + "doc_size": 3 + } + }, + { + "type": "VectorDBTool", + "name": "tech_news_knowledge_base", + "description": "This tool provides recent tech news.", + "parameters": { + "input": "${parameters.question}", + "index": "test_tech_news", + "source_field": [ + "passage" + ], + "model_id": "your_text_embedding_model_id", + "embedding_field": "passage_embedding", + "doc_size": 2 + } + } + ], + "app_type": "chat_with_rag" +} +``` +{% include copy-curl.html %} + +Note the agent ID; you'll use it in the next step. + +## Step 4: Test the agent + +The `conversational` agent supports a `verbose` option. You can set `verbose` to `true` to obtain detailed steps. + +Alternatively, you can call the [Get Message Traces API](ml-commons-plugin/api/memory-apis/get-message-traces/): + +```json +GET _plugins/_ml/memory/message/message_id/traces +``` +{% include copy-curl.html %} + +### Start a conversation + +Ask a question related to tech news: + +```json +POST _plugins/_ml/agents/your_agent_id/_execute +{ + "parameters": { + "question": "What's vision pro", + "verbose": true + } +} +``` +{% include copy-curl.html %} + +In the response, note that the agent runs the `tech_news_knowledge_base` tool to obtain the top two documents. The agent then passes these documents as context to the LLM. The LLM uses the context to produce the answer: + +```json +{ + "inference_results": [ + { + "output": [ + { + "name": "memory_id", + "result": "eLVSxI0B8vrNLhb9nxto" + }, + { + "name": "parent_interaction_id", + "result": "ebVSxI0B8vrNLhb9nxty" + }, + { + "name": "response", + "result": """{ + "thought": "I don't have enough context to answer the question directly. Let me check the tech_news_knowledge_base tool to see if it can provide more information.", + "action": "tech_news_knowledge_base", + "action_input": "{\"query\":\"What's vision pro\"}" +}""" + }, + { + "name": "response", + "result": """{"_index":"test_tech_news","_source":{"passage":"Apple Vision Pro is a mixed-reality headset developed by Apple Inc. It was announced on June 5, 2023, at Apple\u0027s Worldwide Developers Conference, and pre-orders began on January 19, 2024. It became available for purchase on February 2, 2024, in the United States.[10] A worldwide launch has yet to be scheduled. The Vision Pro is Apple\u0027s first new major product category since the release of the Apple Watch in 2015.[11]\n\nApple markets the Vision Pro as a \"spatial computer\" where digital media is integrated with the real world. Physical inputs—such as motion gestures, eye tracking, and speech recognition—can be used to interact with the system.[10] Apple has avoided marketing the device as a virtual reality headset, along with the use of the terms \"virtual reality\" and \"augmented reality\" when discussing the product in presentations and marketing.[12]\n\nThe device runs visionOS,[13] a mixed-reality operating system derived from iOS frameworks using a 3D user interface; it supports multitasking via windows that appear to float within the user\u0027s surroundings,[14] as seen by cameras built into the headset. A dial on the top of the headset can be used to mask the camera feed with a virtual environment to increase immersion. The OS supports avatars (officially called \"Personas\"), which are generated by scanning the user\u0027s face; a screen on the front of the headset displays a rendering of the avatar\u0027s eyes (\"EyeSight\"), which are used to indicate the user\u0027s level of immersion to bystanders, and assist in communication.[15]"},"_id":"lrU8xI0B8vrNLhb9yBpV","_score":0.6700683} +{"_index":"test_tech_news","_source":{"passage":"Amazon Bedrock is a fully managed service that offers a choice of high-performing foundation models (FMs) from leading AI companies like AI21 Labs, Anthropic, Cohere, Meta, Stability AI, and Amazon via a single API, along with a broad set of capabilities you need to build generative AI applications with security, privacy, and responsible AI. Using Amazon Bedrock, you can easily experiment with and evaluate top FMs for your use case, privately customize them with your data using techniques such as fine-tuning and Retrieval Augmented Generation (RAG), and build agents that execute tasks using your enterprise systems and data sources. Since Amazon Bedrock is serverless, you don\u0027t have to manage any infrastructure, and you can securely integrate and deploy generative AI capabilities into your applications using the AWS services you are already familiar with."},"_id":"mLU8xI0B8vrNLhb9yBpV","_score":0.5604863} +""" + }, + { + "name": "response", + "result": "Vision Pro is a mixed-reality headset developed by Apple that was announced in 2023. It uses cameras and sensors to overlay digital objects and information on the real world. The device runs an operating system called visionOS that allows users to interact with windows and apps in a 3D environment using gestures, eye tracking, and voice commands." + } + ] + } + ] +} +``` + +You can trace the detailed steps by using the Get Traces API: + +``` +GET _plugins/_ml/memory/message/ebVSxI0B8vrNLhb9nxty/traces +``` +{% include copy-curl.html %} + +Ask a question related to the population data: + +```json +POST _plugins/_ml/agents/your_agent_id/_execute +{ + "parameters": { + "question": "What's the population of Seattle 2023", + "verbose": true + } +} +``` +{% include copy-curl.html %} + +In the response, note that the agent runs the `population_data_knowledge_base` tool to obtain the top three documents. The agent then passes these documents as context to the LLM. The LLM uses the context to produce the answer: + +```json +{ + "inference_results": [ + { + "output": [ + { + "name": "memory_id", + "result": "l7VUxI0B8vrNLhb9sRuQ" + }, + { + "name": "parent_interaction_id", + "result": "mLVUxI0B8vrNLhb9sRub" + }, + { + "name": "response", + "result": """{ + "thought": "Let me check the population data tool to find the most recent population estimate for Seattle", + "action": "population_data_knowledge_base", + "action_input": "{\"city\":\"Seattle\"}" +}""" + }, + { + "name": "response", + "result": """{"_index":"test_population_data","_source":{"population_description":"Chart and table of population level and growth rate for the Seattle metro area from 1950 to 2023. United Nations population projections are also included through the year 2035.\\nThe current metro area population of Seattle in 2023 is 3,519,000, a 0.86% increase from 2022.\\nThe metro area population of Seattle in 2022 was 3,489,000, a 0.81% increase from 2021.\\nThe metro area population of Seattle in 2021 was 3,461,000, a 0.82% increase from 2020.\\nThe metro area population of Seattle in 2020 was 3,433,000, a 0.79% increase from 2019."},"_id":"BxF5vo0BubpYKX5ER0fT","_score":0.65775126} +{"_index":"test_population_data","_source":{"population_description":"Chart and table of population level and growth rate for the Seattle metro area from 1950 to 2023. United Nations population projections are also included through the year 2035.\\nThe current metro area population of Seattle in 2023 is 3,519,000, a 0.86% increase from 2022.\\nThe metro area population of Seattle in 2022 was 3,489,000, a 0.81% increase from 2021.\\nThe metro area population of Seattle in 2021 was 3,461,000, a 0.82% increase from 2020.\\nThe metro area population of Seattle in 2020 was 3,433,000, a 0.79% increase from 2019."},"_id":"7DrZvo0BVR2NrurbRIAE","_score":0.65775126} +{"_index":"test_population_data","_source":{"population_description":"Chart and table of population level and growth rate for the New York City metro area from 1950 to 2023. United Nations population projections are also included through the year 2035.\\nThe current metro area population of New York City in 2023 is 18,937,000, a 0.37% increase from 2022.\\nThe metro area population of New York City in 2022 was 18,867,000, a 0.23% increase from 2021.\\nThe metro area population of New York City in 2021 was 18,823,000, a 0.1% increase from 2020.\\nThe metro area population of New York City in 2020 was 18,804,000, a 0.01% decline from 2019."},"_id":"AxF5vo0BubpYKX5ER0fT","_score":0.56461215} +""" + }, + { + "name": "response", + "result": "According to the population data tool, the population of Seattle in 2023 is approximately 3,519,000 people, a 0.86% increase from 2022." + } + ] + } + ] +} +``` + +### Continue a conversation + +To continue a previous conversation, provide its conversation ID in the `memory_id` parameter: + +```json +POST _plugins/_ml/agents/your_agent_id/_execute +{ + "parameters": { + "question": "What's the population of Austin 2023, compared with Seattle", + "memory_id": "l7VUxI0B8vrNLhb9sRuQ", + "verbose": true + } +} +``` +{% include copy-curl.html %} + +In the response, note that the `population_data_knowledge_base` doesn't return the population of Seattle. Instead, the agent learns the population of Seattle by referencing historical messages: + +```json +{ + "inference_results": [ + { + "output": [ + { + "name": "memory_id", + "result": "l7VUxI0B8vrNLhb9sRuQ" + }, + { + "name": "parent_interaction_id", + "result": "B7VkxI0B8vrNLhb9mxy0" + }, + { + "name": "response", + "result": """{ + "thought": "Let me check the population data tool first", + "action": "population_data_knowledge_base", + "action_input": "{\"city\":\"Austin\",\"year\":2023}" +}""" + }, + { + "name": "response", + "result": """{"_index":"test_population_data","_source":{"population_description":"Chart and table of population level and growth rate for the Austin metro area from 1950 to 2023. United Nations population projections are also included through the year 2035.\\nThe current metro area population of Austin in 2023 is 2,228,000, a 2.39% increase from 2022.\\nThe metro area population of Austin in 2022 was 2,176,000, a 2.79% increase from 2021.\\nThe metro area population of Austin in 2021 was 2,117,000, a 3.12% increase from 2020.\\nThe metro area population of Austin in 2020 was 2,053,000, a 3.43% increase from 2019."},"_id":"BhF5vo0BubpYKX5ER0fT","_score":0.69129956} +{"_index":"test_population_data","_source":{"population_description":"Chart and table of population level and growth rate for the Austin metro area from 1950 to 2023. United Nations population projections are also included through the year 2035.\\nThe current metro area population of Austin in 2023 is 2,228,000, a 2.39% increase from 2022.\\nThe metro area population of Austin in 2022 was 2,176,000, a 2.79% increase from 2021.\\nThe metro area population of Austin in 2021 was 2,117,000, a 3.12% increase from 2020.\\nThe metro area population of Austin in 2020 was 2,053,000, a 3.43% increase from 2019."},"_id":"6zrZvo0BVR2NrurbRIAE","_score":0.69129956} +{"_index":"test_population_data","_source":{"population_description":"Chart and table of population level and growth rate for the New York City metro area from 1950 to 2023. United Nations population projections are also included through the year 2035.\\nThe current metro area population of New York City in 2023 is 18,937,000, a 0.37% increase from 2022.\\nThe metro area population of New York City in 2022 was 18,867,000, a 0.23% increase from 2021.\\nThe metro area population of New York City in 2021 was 18,823,000, a 0.1% increase from 2020.\\nThe metro area population of New York City in 2020 was 18,804,000, a 0.01% decline from 2019."},"_id":"AxF5vo0BubpYKX5ER0fT","_score":0.61015373} +""" + }, + { + "name": "response", + "result": "According to the population data tool, the population of Austin in 2023 is approximately 2,228,000 people, a 2.39% increase from 2022. This is lower than the population of Seattle in 2023 which is approximately 3,519,000 people, a 0.86% increase from 2022." + } + ] + } + ] +} +``` \ No newline at end of file diff --git a/_ml-commons-plugin/tutorials/rag-conversational-agent.md b/_ml-commons-plugin/tutorials/rag-conversational-agent.md new file mode 100644 index 0000000000..86fe38416a --- /dev/null +++ b/_ml-commons-plugin/tutorials/rag-conversational-agent.md @@ -0,0 +1,838 @@ +--- +layout: default +title: RAG chatbot with a conversational flow agent +parent: Tutorials +nav_order: 40 +--- + +# RAG chatbot with a conversational flow agent + +This tutorial explains how to use a conversational flow agent to build a retrieval-augmented generation (RAG) application with your OpenSearch data as a knowledge base. + +Replace the placeholders beginning with the prefix `your_` with your own values. +{: .note} + +An alternative way to build RAG conversational search is to use a RAG pipeline. For more information, see [Conversational search using the Cohere Command model]({{site.url}}{{site.baseurl}}/ml-commons-plugin/tutorials/conversational-search-cohere/). + +## Prerequisite + +In this tutorial, you'll build a RAG application that provides an OpenSearch [k-NN index]({{site.url}}{{site.baseurl}}/search-plugins/knn/knn-index/) as a knowledge base for a large language model (LLM). For data retrieval, you'll use [semantic search]({{site.url}}{{site.baseurl}}/search-plugins/semantic-search/). For a comprehensive semantic search tutorial, see [Neural search tutorial]({{site.url}}{{site.baseurl}}/search-plugins/neural-search-tutorial/). + +First, you'll need to update your cluster settings. If you don't have a dedicated machine learning (ML) node, set `"plugins.ml_commons.only_run_on_ml_node": false`. To avoid triggering a native memory circuit breaker, set `"plugins.ml_commons.native_memory_threshold"` to 100%: + +```json +PUT _cluster/settings +{ + "persistent": { + "plugins.ml_commons.only_run_on_ml_node": false, + "plugins.ml_commons.native_memory_threshold": 100, + "plugins.ml_commons.agent_framework_enabled": true + } +} +``` +{% include copy-curl.html %} + +## Step 1: Prepare the knowledge base + +Use the following steps to prepare the knowledge base that will supplement the LLM's knowledge. + +### Step 1.1: Register a text embedding model + +Register a text embedding model that will translate text into vector embeddings: + +```json +POST /_plugins/_ml/models/_register +{ + "name": "huggingface/sentence-transformers/all-MiniLM-L12-v2", + "version": "1.0.1", + "model_format": "TORCH_SCRIPT" +} +``` +{% include copy-curl.html %} + +Note the text embedding model ID; you'll use it in the following steps. + +As an alternative, you can get the model ID by calling the [Get Task API]({{site.url}}{{site.baseurl}}/ml-commons-plugin/api/tasks-apis/get-task/): + +```json +GET /_plugins/_ml/tasks/your_task_id +``` +{% include copy-curl.html %} + +Deploy the model: + +```json +POST /_plugins/_ml/models/your_text_embedding_model_id/_deploy +``` +{% include copy-curl.html %} + +Test the model: + +```json +POST /_plugins/_ml/models/your_text_embedding_model_id/_predict +{ + "text_docs":[ "today is sunny"], + "return_number": true, + "target_response": ["sentence_embedding"] +} +``` +{% include copy-curl.html %} + +For more information about using models within your OpenSearch cluster, see [Pretrained models]({{site.url}}{{site.baseurl}}/ml-commons-plugin/pretrained-models/). + +### Step 1.2: Create an ingest pipeline + +Create an ingest pipeline with a text embedding processor, which can invoke the model created in the previous step to generate embeddings from text fields: + +```json +PUT /_ingest/pipeline/test_population_data_pipeline +{ + "description": "text embedding pipeline", + "processors": [ + { + "text_embedding": { + "model_id": "your_text_embedding_model_id", + "field_map": { + "population_description": "population_description_embedding" + } + } + } + ] +} +``` +{% include copy-curl.html %} + +For more information about ingest pipelines, see [Ingest pipelines]({{site.url}}{{site.baseurl}}/ingest-pipelines/). + +### Step 1.3: Create a k-NN index + +Create a k-NN index specifying the ingest pipeline as a default pipeline: + +```json +PUT test_population_data +{ + "mappings": { + "properties": { + "population_description": { + "type": "text" + }, + "population_description_embedding": { + "type": "knn_vector", + "dimension": 384 + } + } + }, + "settings": { + "index": { + "knn.space_type": "cosinesimil", + "default_pipeline": "test_population_data_pipeline", + "knn": "true" + } + } +} +``` +{% include copy-curl.html %} + +For more information about k-NN indexes, see [k-NN index]({{site.url}}{{site.baseurl}}/search-plugins/knn/knn-index/). + +### Step 1.4: Ingest data + +Ingest test data into the k-NN index: + +```json +POST _bulk +{"index": {"_index": "test_population_data"}} +{"population_description": "Chart and table of population level and growth rate for the Ogden-Layton metro area from 1950 to 2023. United Nations population projections are also included through the year 2035.\nThe current metro area population of Ogden-Layton in 2023 is 750,000, a 1.63% increase from 2022.\nThe metro area population of Ogden-Layton in 2022 was 738,000, a 1.79% increase from 2021.\nThe metro area population of Ogden-Layton in 2021 was 725,000, a 1.97% increase from 2020.\nThe metro area population of Ogden-Layton in 2020 was 711,000, a 2.16% increase from 2019."} +{"index": {"_index": "test_population_data"}} +{"population_description": "Chart and table of population level and growth rate for the New York City metro area from 1950 to 2023. United Nations population projections are also included through the year 2035.\\nThe current metro area population of New York City in 2023 is 18,937,000, a 0.37% increase from 2022.\\nThe metro area population of New York City in 2022 was 18,867,000, a 0.23% increase from 2021.\\nThe metro area population of New York City in 2021 was 18,823,000, a 0.1% increase from 2020.\\nThe metro area population of New York City in 2020 was 18,804,000, a 0.01% decline from 2019."} +{"index": {"_index": "test_population_data"}} +{"population_description": "Chart and table of population level and growth rate for the Chicago metro area from 1950 to 2023. United Nations population projections are also included through the year 2035.\\nThe current metro area population of Chicago in 2023 is 8,937,000, a 0.4% increase from 2022.\\nThe metro area population of Chicago in 2022 was 8,901,000, a 0.27% increase from 2021.\\nThe metro area population of Chicago in 2021 was 8,877,000, a 0.14% increase from 2020.\\nThe metro area population of Chicago in 2020 was 8,865,000, a 0.03% increase from 2019."} +{"index": {"_index": "test_population_data"}} +{"population_description": "Chart and table of population level and growth rate for the Miami metro area from 1950 to 2023. United Nations population projections are also included through the year 2035.\\nThe current metro area population of Miami in 2023 is 6,265,000, a 0.8% increase from 2022.\\nThe metro area population of Miami in 2022 was 6,215,000, a 0.78% increase from 2021.\\nThe metro area population of Miami in 2021 was 6,167,000, a 0.74% increase from 2020.\\nThe metro area population of Miami in 2020 was 6,122,000, a 0.71% increase from 2019."} +{"index": {"_index": "test_population_data"}} +{"population_description": "Chart and table of population level and growth rate for the Austin metro area from 1950 to 2023. United Nations population projections are also included through the year 2035.\\nThe current metro area population of Austin in 2023 is 2,228,000, a 2.39% increase from 2022.\\nThe metro area population of Austin in 2022 was 2,176,000, a 2.79% increase from 2021.\\nThe metro area population of Austin in 2021 was 2,117,000, a 3.12% increase from 2020.\\nThe metro area population of Austin in 2020 was 2,053,000, a 3.43% increase from 2019."} +{"index": {"_index": "test_population_data"}} +{"population_description": "Chart and table of population level and growth rate for the Seattle metro area from 1950 to 2023. United Nations population projections are also included through the year 2035.\\nThe current metro area population of Seattle in 2023 is 3,519,000, a 0.86% increase from 2022.\\nThe metro area population of Seattle in 2022 was 3,489,000, a 0.81% increase from 2021.\\nThe metro area population of Seattle in 2021 was 3,461,000, a 0.82% increase from 2020.\\nThe metro area population of Seattle in 2020 was 3,433,000, a 0.79% increase from 2019."} +``` +{% include copy-curl.html %} + +## Step 2: Prepare an LLM + +This tutorial uses the [Amazon Bedrock Claude model](https://aws.amazon.com/bedrock/claude/) for conversational search. You can also use other LLMs. For more information about using externally hosted models, see [Connecting to externally hosted models]({{site.url}}{{site.baseurl}}/ml-commons-plugin/remote-models/index/). + +### Step 2.1: Create a connector + +Create a connector for the Claude model: + +```json +POST /_plugins/_ml/connectors/_create +{ + "name": "BedRock Claude instant-v1 Connector ", + "description": "The connector to BedRock service for claude model", + "version": 1, + "protocol": "aws_sigv4", + "parameters": { + "region": "us-east-1", + "service_name": "bedrock", + "anthropic_version": "bedrock-2023-05-31", + "max_tokens_to_sample": 8000, + "temperature": 0.0001, + "response_filter": "$.completion" + }, + "credential": { + "access_key": "your_aws_access_key", + "secret_key": "your_aws_secret_key", + "session_token": "your_aws_session_token" + }, + "actions": [ + { + "action_type": "predict", + "method": "POST", + "url": "https://bedrock-runtime.us-east-1.amazonaws.com/model/anthropic.claude-instant-v1/invoke", + "headers": { + "content-type": "application/json", + "x-amz-content-sha256": "required" + }, + "request_body": "{\"prompt\":\"${parameters.prompt}\", \"max_tokens_to_sample\":${parameters.max_tokens_to_sample}, \"temperature\":${parameters.temperature}, \"anthropic_version\":\"${parameters.anthropic_version}\" }" + } + ] +} +``` +{% include copy-curl.html %} + +Note the connector ID; you'll use it to register the model. + +### Step 2.2: Register the model + +Register the Claude model hosted on Amazon Bedrock: + +```json +POST /_plugins/_ml/models/_register +{ + "name": "Bedrock Claude Instant model", + "function_name": "remote", + "description": "Bedrock Claude instant-v1 model", + "connector_id": "your_LLM_connector_id" +} +``` +{% include copy-curl.html %} + +Note the LLM model ID; you'll use it in the following steps. + +### Step 2.3: Deploy the model + +Deploy the Claude model: + +```json +POST /_plugins/_ml/models/your_LLM_model_id/_deploy +``` +{% include copy-curl.html %} + +### Step 2.4: Test the model + +To test the model, send a Predict API request: + +```json +POST /_plugins/_ml/models/your_LLM_model_id/_predict +{ + "parameters": { + "prompt": "\n\nHuman: how are you? \n\nAssistant:" + } +} +``` +{% include copy-curl.html %} + +## Step 3: Register an agent + +OpenSearch provides the following agent types: `flow`, `conversational_flow`, and `conversational`. For more information about agents, see [Agents]({{site.url}}{{site.baseurl}}/ml-commons-plugin/agents-tools/index/#agents). + +You will use a `conversational_flow` agent in this tutorial. The agent consists of the following: + +- Meta info: `name`, `type`, and `description`. +- `app_type`: Differentiates between application types. +- `memory`: Stores user questions and LLM responses as a conversation so that an agent can retrieve conversation history from memory and continue the same conversation. +- `tools`: Defines a list of tools to use. The agent will run these tools sequentially. + +To register an agent, send the following request: + +```json +POST /_plugins/_ml/agents/_register +{ + "name": "population data analysis agent", + "type": "conversational_flow", + "description": "This is a demo agent for population data analysis", + "app_type": "rag", + "memory": { + "type": "conversation_index" + }, + "tools": [ + { + "type": "VectorDBTool", + "name": "population_knowledge_base", + "parameters": { + "model_id": "your_text_embedding_model_id", + "index": "test_population_data", + "embedding_field": "population_description_embedding", + "source_field": [ + "population_description" + ], + "input": "${parameters.question}" + } + }, + { + "type": "MLModelTool", + "name": "bedrock_claude_model", + "description": "A general tool to answer any question", + "parameters": { + "model_id": "your_LLM_model_id", + "prompt": "\n\nHuman:You are a professional data analysist. You will always answer question based on the given context first. If the answer is not directly shown in the context, you will analyze the data and find the answer. If you don't know the answer, just say don't know. \n\nContext:\n${parameters.population_knowledge_base.output:-}\n\n${parameters.chat_history:-}\n\nHuman:${parameters.question}\n\nAssistant:" + } + } + ] +} +``` +{% include copy-curl.html %} + +OpenSearch responds with an agent ID: + +```json +{ + "agent_id": "fQ75lI0BHcHmo_czdqcJ" +} +``` + +Note the agent ID; you'll use it in the next step. + +## Step 4: Run the agent + +You'll run the agent to analyze the increase in Seattle's population. When you run this agent, the agent will create a new conversation. Later, you can continue this conversation by asking other questions. + +### Step 4.1: Start a new conversation + +First, start a new conversation by asking the LLM a question: + +```json +POST /_plugins/_ml/agents/your_agent_id/_execute +{ + "parameters": { + "question": "what's the population increase of Seattle from 2021 to 2023?" + } +} +``` +{% include copy-curl.html %} + +The response contains the answer generated by the LLM: + +```json +{ + "inference_results": [ + { + "output": [ + { + "name": "memory_id", + "result": "gQ75lI0BHcHmo_cz2acL" + }, + { + "name": "parent_message_id", + "result": "gg75lI0BHcHmo_cz2acZ" + }, + { + "name": "bedrock_claude_model", + "result": """ Based on the context given: +- The metro area population of Seattle in 2021 was 3,461,000 +- The current metro area population of Seattle in 2023 is 3,519,000 +- So the population increase of Seattle from 2021 to 2023 is 3,519,000 - 3,461,000 = 58,000""" + } + ] + } + ] +} +``` + +The response contains the following fields: + +- `memory_id` is the identifier for the memory (conversation) that groups all messages within a single conversation. Note this ID; you'll use it in the next step. +- `parent_message_id` is the identifier for the current message (one question/answer) between the human and the LLM. One memory can contain multiple messages. + +To obtain memory details, call the [Get Memory API](ml-commons-plugin/api/memory-apis/get-memory/): + +```json +GET /_plugins/_ml/memory/gQ75lI0BHcHmo_cz2acL +``` +{% include copy-curl.html %} + +To obtain all messages within a memory, call the [Get Messages API](ml-commons-plugin/api/memory-apis/get-message/): + +```json +GET /_plugins/_ml/memory/gQ75lI0BHcHmo_cz2acL/messages +``` +{% include copy-curl.html %} + +To obtain message details, call the [Get Message API](ml-commons-plugin/api/memory-apis/get-message/): + +```json +GET /_plugins/_ml/memory/message/gg75lI0BHcHmo_cz2acZ +``` +{% include copy-curl.html %} + +For debugging purposes, you can obtain trace data for a message by calling the [Get Message Traces API](ml-commons-plugin/api/memory-apis/get-message-traces/): + +```json +GET /_plugins/_ml/memory/message/gg75lI0BHcHmo_cz2acZ/traces +``` +{% include copy-curl.html %} + +### 4.2 Continue a conversation by asking new questions + +To continue the same conversation, provide the memory ID from the previous step. + +Additionally, you can provide the following parameters: + +- `message_history_limit`: Specify how many historical messages you want included in the new question/answer round for an agent. +- `prompt`: Use this parameter to customize the LLM prompt. For example, the following example adds a new instruction `always learn useful information from chat history` +and a new parameter `next_action`: + +```json +POST /_plugins/_ml/agents/your_agent_id/_execute +{ + "parameters": { + "question": "What's the population of New York City in 2023?", + "next_action": "then compare with Seattle population of 2023", + "memory_id": "gQ75lI0BHcHmo_cz2acL", + "message_history_limit": 5, + "prompt": "\n\nHuman:You are a professional data analysist. You will always answer question based on the given context first. If the answer is not directly shown in the context, you will analyze the data and find the answer. If you don't know the answer, just say don't know. \n\nContext:\n${parameters.population_knowledge_base.output:-}\n\n${parameters.chat_history:-}\n\nHuman:always learn useful information from chat history\nHuman:${parameters.question}, ${parameters.next_action}\n\nAssistant:" + } +} +``` +{% include copy-curl.html %} + +The response contains the answer generated by the LLM: + +```json +{ + "inference_results": [ + { + "output": [ + { + "name": "memory_id", + "result": "gQ75lI0BHcHmo_cz2acL" + }, + { + "name": "parent_message_id", + "result": "wQ4JlY0BHcHmo_cz8Kc-" + }, + { + "name": "bedrock_claude_model", + "result": """ Based on the context given: +- The current metro area population of New York City in 2023 is 18,937,000 +- The current metro area population of Seattle in 2023 is 3,519,000 +- So the population of New York City in 2023 (18,937,000) is much higher than the population of Seattle in 2023 (3,519,000)""" + } + ] + } + ] +} +``` + +If you know which tool the agent should use to execute a particular Predict API request, you can specify the tool when executing the agent. For example, if you want to translate the preceding answer into Chinese, you don't need to retrieve any data from the knowledge base. To run only the Claude model, specify the `bedrock_claude_model` tool in the `selected_tools` parameter: + +```json +POST /_plugins/_ml/agents/your_agent_id/_execute +{ + "parameters": { + "question": "Translate last answer into Chinese?", + "selected_tools": ["bedrock_claude_model"] + } +} +``` +{% include copy-curl.html %} + +The agent will run the tools one by one in the new order defined in `selected_tools`. +{: .note} + +## Configuring multiple knowledge bases + +You can configure multiple knowledge bases for an agent. For example, if you have both product description and comment data, you can configure the agent with the following two tools: + +```json +{ + "name": "My product agent", + "type": "conversational_flow", + "description": "This is an agent with product description and comments knowledge bases.", + "memory": { + "type": "conversation_index" + }, + "app_type": "rag", + "tools": [ + { + "type": "VectorDBTool", + "name": "product_description_vectordb", + "parameters": { + "model_id": "your_embedding_model_id", + "index": "product_description_data", + "embedding_field": "product_description_embedding", + "source_field": [ + "product_description" + ], + "input": "${parameters.question}" + } + }, + { + "type": "VectorDBTool", + "name": "product_comments_vectordb", + "parameters": { + "model_id": "your_embedding_model_id", + "index": "product_comments_data", + "embedding_field": "product_comment_embedding", + "source_field": [ + "product_comment" + ], + "input": "${parameters.question}" + } + }, + { + "type": "MLModelTool", + "description": "A general tool to answer any question", + "parameters": { + "model_id": "{{llm_model_id}}", + "prompt": "\n\nHuman:You are a professional product recommendation engine. You will always recommend product based on the given context. If you don't have enough context, you will ask Human to provide more information. If you don't see any related product to recommend, just say we don't have such product. \n\n Context:\n${parameters.product_description_vectordb.output}\n\n${parameters.product_comments_vectordb.output}\n\nHuman:${parameters.question}\n\nAssistant:" + } + } + ] +} +``` +{% include copy-curl.html %} + +When you run the agent, the agent will query product description and comment data and then send the query results and the question to the LLM. + +To query a specific knowledge base, specify it in `selected_tools`. For example, if the question relates only to product comments, you can retrieve information only from `product_comments_vectordb`: + +```json +POST /_plugins/_ml/agents/your_agent_id/_execute +{ + "parameters": { + "question": "What feature people like the most for Amazon Echo Dot", + "selected_tools": ["product_comments_vectordb", "MLModelTool"] + } +} +``` +{% include copy-curl.html %} + +## Running queries on an index + +Use `SearchIndexTool` to run any OpenSearch query on any index. + +### Setup: Register an agent + +```json +POST /_plugins/_ml/agents/_register +{ + "name": "Demo agent", + "type": "conversational_flow", + "description": "This agent supports running any search query", + "memory": { + "type": "conversation_index" + }, + "app_type": "rag", + "tools": [ + { + "type": "SearchIndexTool", + "parameters": { + "input": "{\"index\": \"${parameters.index}\", \"query\": ${parameters.query} }" + } + }, + { + "type": "MLModelTool", + "description": "A general tool to answer any question", + "parameters": { + "model_id": "your_llm_model_id", + "prompt": "\n\nHuman:You are a professional data analysist. You will always answer question based on the given context first. If the answer is not directly shown in the context, you will analyze the data and find the answer. If you don't know the answer, just say don't know. \n\n Context:\n${parameters.SearchIndexTool.output:-}\n\nHuman:${parameters.question}\n\nAssistant:" + } + } + ] +} +``` +{% include copy-curl.html %} + +### Run a BM25 query + +```json +POST /_plugins/_ml/agents/your_agent_id/_execute +{ + "parameters": { + "question": "what's the population increase of Seattle from 2021 to 2023?", + "index": "test_population_data", + "query": { + "query": { + "match": { + "population_description": "${parameters.question}" + } + }, + "size": 2, + "_source": "population_description" + } + } +} +``` +{% include copy-curl.html %} + +### Exposing only the `question` parameter + +To expose only the `question` parameter, define the agent as follows: + +```json +POST /_plugins/_ml/agents/_register +{ + "name": "Demo agent", + "type": "conversational_flow", + "description": "This is a test agent support running any search query", + "memory": { + "type": "conversation_index" + }, + "app_type": "rag", + "tools": [ + { + "type": "SearchIndexTool", + "parameters": { + "input": "{\"index\": \"${parameters.index}\", \"query\": ${parameters.query} }", + "index": "test_population_data", + "query": { + "query": { + "match": { + "population_description": "${parameters.question}" + } + }, + "size": 2, + "_source": "population_description" + } + } + }, + { + "type": "MLModelTool", + "description": "A general tool to answer any question", + "parameters": { + "model_id": "your_llm_model_id", + "prompt": "\n\nHuman:You are a professional data analyst. You will always answer question based on the given context first. If the answer is not directly shown in the context, you will analyze the data and find the answer. If you don't know the answer, just say don't know. \n\n Context:\n${parameters.SearchIndexTool.output:-}\n\nHuman:${parameters.question}\n\nAssistant:" + } + } + ] +} +``` +{% include copy-curl.html %} + +Now you can run the agent specifying only the `question` parameter: + +```json +POST /_plugins/_ml/agents/your_agent_id/_execute +{ + "parameters": { + "question": "what's the population increase of Seattle from 2021 to 2023?" + } +} +``` +{% include copy-curl.html %} + +### Run a neural search query + +```json +POST /_plugins/_ml/agents/your_agent_id/_execute +{ + "parameters": { + "question": "what's the population increase of Seattle from 2021 to 2023??", + "index": "test_population_data", + "query": { + "query": { + "neural": { + "population_description_embedding": { + "query_text": "${parameters.question}", + "model_id": "your_embedding_model_id", + "k": 10 + } + } + }, + "size": 2, + "_source": ["population_description"] + } + } +} +``` +{% include copy-curl.html %} + +To expose the `question` parameter, see [Exposing only the `question` parameter](#exposing-only-the-question-parameter). + +### Run a hybrid search query + +Hybrid search combines keyword and neural search to improve search relevance. For more information, see [Hybrid search]({{site.url}}{{site.baseurl}}/search-plugins/hybrid-search/). + +Configure a search pipeline: + +```json +PUT /_search/pipeline/nlp-search-pipeline +{ + "description": "Post processor for hybrid search", + "phase_results_processors": [ + { + "normalization-processor": { + "normalization": { + "technique": "min_max" + }, + "combination": { + "technique": "arithmetic_mean", + "parameters": { + "weights": [ + 0.3, + 0.7 + ] + } + } + } + } + ] + } +``` +{% include copy-curl.html %} + +Run an agent with a hybrid query: + +```json +POST /_plugins/_ml/agents/your_agent_id/_execute +{ + "parameters": { + "question": "what's the population increase of Seattle from 2021 to 2023??", + "index": "test_population_data", + "query": { + "_source": { + "exclude": [ + "population_description_embedding" + ] + }, + "size": 2, + "query": { + "hybrid": { + "queries": [ + { + "match": { + "population_description": { + "query": "${parameters.question}" + } + } + }, + { + "neural": { + "population_description_embedding": { + "query_text": "${parameters.question}", + "model_id": "your_embedding_model_id", + "k": 10 + } + } + } + ] + } + } + } + } +} +``` +{% include copy-curl.html %} + +To expose the `question` parameter, see [Exposing only the `question` parameter](#exposing-only-the-question-parameter). + +### Natural language query + +The `PPLTool` can translate a natural language query (NLQ) to [Piped Processing Language (PPL)]({{site.url}}{{site.baseurl}}/search-plugins/sql/ppl/index/) and execute the generated PPL query. + +#### Setup + +Before you start, go to the OpenSearch Dashboards home page, select `Add sample data`, and then add `Sample eCommerce orders`. + + +#### Step 1: Register an agent with the PPLTool + + +The `PPLTool` has the following parameters: + +- `model_type` (Enum): `CLAUDE`, `OPENAI`, or `FINETUNE`. +- `execute` (Boolean): If `true`, executes the generated PPL query. +- `input` (String): You must provide the `index` and `question` as inputs. + +For this tutorial, you'll use Bedrock Claude, so set the `model_type` to `CLAUDE`: + +```json +POST /_plugins/_ml/agents/_register +{ + "name": "Demo agent for NLQ", + "type": "conversational_flow", + "description": "This is a test flow agent for NLQ", + "memory": { + "type": "conversation_index" + }, + "app_type": "rag", + "tools": [ + { + "type": "PPLTool", + "parameters": { + "model_id": "your_ppl_model_id", + "model_type": "CLAUDE", + "execute": true, + "input": "{\"index\": \"${parameters.index}\", \"question\": ${parameters.question} }" + } + }, + { + "type": "MLModelTool", + "description": "A general tool to answer any question", + "parameters": { + "model_id": "your_llm_model_id", + "prompt": "\n\nHuman:You are a professional data analysist. You will always answer question based on the given context first. If the answer is not directly shown in the context, you will analyze the data and find the answer. If you don't know the answer, just say don't know. \n\n Context:\n${parameters.PPLTool.output:-}\n\nHuman:${parameters.question}\n\nAssistant:" + } + } + ] +} +``` +{% include copy-curl.html %} + +### Step 2: Run the agent with an NLQ + +Run the agent: + +```json +POST /_plugins/_ml/agents/your_agent_id/_execute +{ + "parameters": { + "question": "How many orders do I have in last week", + "index": "opensearch_dashboards_sample_data_ecommerce" + } +} +``` +{% include copy-curl.html %} + +The response contains the answer generated by the LLM: + +```json +{ + "inference_results": [ + { + "output": [ + { + "name": "memory_id", + "result": "sqIioI0BJhBwrVXYeYOM" + }, + { + "name": "parent_message_id", + "result": "s6IioI0BJhBwrVXYeYOW" + }, + { + "name": "MLModelTool", + "result": " Based on the given context, the number of orders in the last week is 3992. The data shows a query that counts the number of orders where the order date is greater than 1 week ago. The query result shows the count as 3992." + } + ] + } + ] +} +``` + +For more information, obtain trace data by calling the [Get Message Traces API]({{site.url}}{{site.baseurl}}/ml-commons-plugin/api/memory-apis/get-message-traces/): + +```json +GET _plugins/_ml/memory/message/s6IioI0BJhBwrVXYeYOW/traces +``` +{% include copy-curl.html %} \ No newline at end of file diff --git a/_ml-commons-plugin/tutorials/reranking-cohere.md b/_ml-commons-plugin/tutorials/reranking-cohere.md new file mode 100644 index 0000000000..412180066f --- /dev/null +++ b/_ml-commons-plugin/tutorials/reranking-cohere.md @@ -0,0 +1,344 @@ +--- +layout: default +title: Reranking with Cohere Rerank +parent: Tutorials +nav_order: 30 +--- + +# Reranking search results using the Cohere Rerank model + +A [reranking pipeline]({{site.url}}{{site.baseurl}}/search-plugins/search-relevance/reranking-search-results/) can rerank search results, providing a relevance score for each document in the search results with respect to the search query. The relevance score is calculated by a cross-encoder model. + +This tutorial illustrates how to use the [Cohere Rerank](https://docs.cohere.com/reference/rerank-1) model in a reranking pipeline. + +Replace the placeholders beginning with the prefix `your_` with your own values. +{: .note} + +## Step 1: Register a Cohere Rerank model + +Create a connector for the Cohere Rerank model: + +```json +POST /_plugins/_ml/connectors/_create +{ + "name": "cohere-rerank", + "description": "The connector to Cohere reanker model", + "version": "1", + "protocol": "http", + "credential": { + "cohere_key": "your_cohere_api_key" + }, + "parameters": { + "model": "rerank-english-v2.0" + }, + "actions": [ + { + "action_type": "predict", + "method": "POST", + "url": "https://api.cohere.ai/v1/rerank", + "headers": { + "Authorization": "Bearer ${credential.cohere_key}" + }, + "request_body": "{ \"documents\": ${parameters.documents}, \"query\": \"${parameters.query}\", \"model\": \"${parameters.model}\", \"top_n\": ${parameters.top_n} }", + "pre_process_function": "connector.pre_process.cohere.rerank", + "post_process_function": "connector.post_process.cohere.rerank" + } + ] +} +``` +{% include copy-curl.html %} + +Use the connector ID from the response to register a Cohere Rerank model: + +```json +POST /_plugins/_ml/models/_register?deploy=true +{ + "name": "cohere rerank model", + "function_name": "remote", + "description": "test rerank model", + "connector_id": "your_connector_id" +} +``` +{% include copy-curl.html %} + +Note the model ID in the response; you'll use it in the following steps. + +Test the model by calling the Predict API: + +```json +POST _plugins/_ml/models/your_model_id/_predict +{ + "parameters": { + "query": "What is the capital of the United States?", + "documents": [ + "Carson City is the capital city of the American state of Nevada.", + "The Commonwealth of the Northern Mariana Islands is a group of islands in the Pacific Ocean. Its capital is Saipan.", + "Washington, D.C. (also known as simply Washington or D.C., and officially as the District of Columbia) is the capital of the United States. It is a federal district.", + "Capital punishment (the death penalty) has existed in the United States since beforethe United States was a country. As of 2017, capital punishment is legal in 30 of the 50 states." + ], + "top_n": 4 + } +} +``` + +To ensure compatibility with the rerank pipeline, the `top_n` value must be the same as the length of the `documents` list. +{: .important} + +You can customize the number of top documents returned in the response by providing the `size` parameter. For more information, see [Step 2.3](#step-23-test-the-reranking). + +OpenSearch responds with the inference results: + +```json +{ + "inference_results": [ + { + "output": [ + { + "name": "similarity", + "data_type": "FLOAT32", + "shape": [ + 1 + ], + "data": [ + 0.10194652 + ] + }, + { + "name": "similarity", + "data_type": "FLOAT32", + "shape": [ + 1 + ], + "data": [ + 0.0721122 + ] + }, + { + "name": "similarity", + "data_type": "FLOAT32", + "shape": [ + 1 + ], + "data": [ + 0.98005307 + ] + }, + { + "name": "similarity", + "data_type": "FLOAT32", + "shape": [ + 1 + ], + "data": [ + 0.27904198 + ] + } + ], + "status_code": 200 + } + ] +} +``` + +The response contains four `similarity` objects. For each `similarity` object, the `data` array contains a relevance score for each document with respect to the query. The `similarity` objects are provided in the order of the input documents; the first object pertains to the first document. This differs from the default output of the Cohere Rerank model, which orders documents by relevance score. The document order is changed in the `connector.post_process.cohere.rerank` post-processing function in order to make the output compatible with a reranking pipeline. + +## Step 2: Configure a reranking pipeline + +Follow these steps to configure a reranking pipeline. + +### Step 2.1: Ingest test data + +Send a bulk request to ingest test data: + +```json +POST _bulk +{ "index": { "_index": "my-test-data" } } +{ "passage_text" : "Carson City is the capital city of the American state of Nevada." } +{ "index": { "_index": "my-test-data" } } +{ "passage_text" : "The Commonwealth of the Northern Mariana Islands is a group of islands in the Pacific Ocean. Its capital is Saipan." } +{ "index": { "_index": "my-test-data" } } +{ "passage_text" : "Washington, D.C. (also known as simply Washington or D.C., and officially as the District of Columbia) is the capital of the United States. It is a federal district." } +{ "index": { "_index": "my-test-data" } } +{ "passage_text" : "Capital punishment (the death penalty) has existed in the United States since beforethe United States was a country. As of 2017, capital punishment is legal in 30 of the 50 states." } +``` +{% include copy-curl.html %} + +### Step 2.2: Create a reranking pipeline + +Create a reranking pipeline with the Cohere Rerank model: + +```json +PUT /_search/pipeline/rerank_pipeline_cohere +{ + "description": "Pipeline for reranking with Cohere Rerank model", + "response_processors": [ + { + "rerank": { + "ml_opensearch": { + "model_id": "your_model_id_created_in_step1" + }, + "context": { + "document_fields": ["passage_text"] + } + } + } + ] +} +``` +{% include copy-curl.html %} + +### Step 2.3: Test the reranking + +To limit the number of returned results, you can specify the `size` parameter. For example, set `"size": 2` to return the top two documents: + +```json +GET my-test-data/_search?search_pipeline=rerank_pipeline_cohere +{ + "query": { + "match_all": {} + }, + "size": 4, + "ext": { + "rerank": { + "query_context": { + "query_text": "What is the capital of the United States?" + } + } + } +} +``` +{% include copy-curl.html %} + +The response contains the two most relevant documents: + +```json +{ + "took": 0, + "timed_out": false, + "_shards": { + "total": 1, + "successful": 1, + "skipped": 0, + "failed": 0 + }, + "hits": { + "total": { + "value": 4, + "relation": "eq" + }, + "max_score": 0.98005307, + "hits": [ + { + "_index": "my-test-data", + "_id": "zbUOw40B8vrNLhb9vBif", + "_score": 0.98005307, + "_source": { + "passage_text": "Washington, D.C. (also known as simply Washington or D.C., and officially as the District of Columbia) is the capital of the United States. It is a federal district." + } + }, + { + "_index": "my-test-data", + "_id": "zrUOw40B8vrNLhb9vBif", + "_score": 0.27904198, + "_source": { + "passage_text": "Capital punishment (the death penalty) has existed in the United States since beforethe United States was a country. As of 2017, capital punishment is legal in 30 of the 50 states." + } + }, + { + "_index": "my-test-data", + "_id": "y7UOw40B8vrNLhb9vBif", + "_score": 0.10194652, + "_source": { + "passage_text": "Carson City is the capital city of the American state of Nevada." + } + }, + { + "_index": "my-test-data", + "_id": "zLUOw40B8vrNLhb9vBif", + "_score": 0.0721122, + "_source": { + "passage_text": "The Commonwealth of the Northern Mariana Islands is a group of islands in the Pacific Ocean. Its capital is Saipan." + } + } + ] + }, + "profile": { + "shards": [] + } +} +``` + +To compare these results to results without reranking, run the search without a reranking pipeline: + +```json +GET my-test-data/_search +{ + "query": { + "match_all": {} + }, + "ext": { + "rerank": { + "query_context": { + "query_text": "What is the capital of the United States?" + } + } + } +} +``` +{% include copy-curl.html %} + +The first document in the response pertains to Carson City, which is not the capital of the United States: + +```json +{ + "took": 0, + "timed_out": false, + "_shards": { + "total": 1, + "successful": 1, + "skipped": 0, + "failed": 0 + }, + "hits": { + "total": { + "value": 4, + "relation": "eq" + }, + "max_score": 1, + "hits": [ + { + "_index": "my-test-data", + "_id": "y7UOw40B8vrNLhb9vBif", + "_score": 1, + "_source": { + "passage_text": "Carson City is the capital city of the American state of Nevada." + } + }, + { + "_index": "my-test-data", + "_id": "zLUOw40B8vrNLhb9vBif", + "_score": 1, + "_source": { + "passage_text": "The Commonwealth of the Northern Mariana Islands is a group of islands in the Pacific Ocean. Its capital is Saipan." + } + }, + { + "_index": "my-test-data", + "_id": "zbUOw40B8vrNLhb9vBif", + "_score": 1, + "_source": { + "passage_text": "Washington, D.C. (also known as simply Washington or D.C., and officially as the District of Columbia) is the capital of the United States. It is a federal district." + } + }, + { + "_index": "my-test-data", + "_id": "zrUOw40B8vrNLhb9vBif", + "_score": 1, + "_source": { + "passage_text": "Capital punishment (the death penalty) has existed in the United States since beforethe United States was a country. As of 2017, capital punishment is legal in 30 of the 50 states." + } + } + ] + } +} +``` \ No newline at end of file diff --git a/_ml-commons-plugin/tutorials/semantic-search-byte-vectors.md b/_ml-commons-plugin/tutorials/semantic-search-byte-vectors.md new file mode 100644 index 0000000000..7061d3cb5a --- /dev/null +++ b/_ml-commons-plugin/tutorials/semantic-search-byte-vectors.md @@ -0,0 +1,314 @@ +--- +layout: default +title: Semantic search using byte vectors +parent: Tutorials +nav_order: 10 +--- + +# Semantic search using byte-quantized vectors + +This tutorial illustrates how to build a semantic search using the [Cohere Embed model](https://docs.cohere.com/reference/embed) and byte-quantized vectors. For more information about using byte-quantized vectors, see [Lucene byte vector]({{site.url}}{{site.baseurl}}/field-types/supported-field-types/knn-vector/#lucene-byte-vector). + +The Cohere Embed v3 model supports several `embedding_types`. For this tutorial, you'll use the `INT8` type to encode byte-quantized vectors. + +The Cohere Embed v3 model supports several input types. This tutorial uses the following input types: + +- `search_document`: Use this input type when you have text (in the form of documents) that you want to store in a vector database. +- `search_query`: Use this input type when structuring search queries to find the most relevant documents in your vector database. + +For more information about input types, see the [Cohere documentation](https://docs.cohere.com/docs/embed-api#the-input_type-parameter). + +In this tutorial, you will create two models: + +- A model used for ingestion, whose `input_type` is `search_document` +- A model used for search, whose `input_type` is `search_query` + +Replace the placeholders beginning with the prefix `your_` with your own values. +{: .note} + +## Step 1: Create an embedding model for ingestion + +Create a connector for the Cohere model, specifying the `search_document` input type: + +```json +POST /_plugins/_ml/connectors/_create +{ + "name": "Cohere embedding connector with int8 embedding type for ingestion", + "description": "Test connector for Cohere embedding model", + "version": 1, + "protocol": "http", + "credential": { + "cohere_key": "your_cohere_api_key" + }, + "parameters": { + "model": "embed-english-v3.0", + "embedding_types": ["int8"], + "input_type": "search_document" + }, + "actions": [ + { + "action_type": "predict", + "method": "POST", + "headers": { + "Authorization": "Bearer ${credential.cohere_key}", + "Request-Source": "unspecified:opensearch" + }, + "url": "https://api.cohere.ai/v1/embed", + "request_body": "{ \"model\": \"${parameters.model}\", \"texts\": ${parameters.texts}, \"input_type\":\"${parameters.input_type}\", \"embedding_types\": ${parameters.embedding_types} }", + "pre_process_function": "connector.pre_process.cohere.embedding", + "post_process_function": "\n def name = \"sentence_embedding\";\n def data_type = \"FLOAT32\";\n def result;\n if (params.embeddings.int8 != null) {\n data_type = \"INT8\";\n result = params.embeddings.int8;\n } else if (params.embeddings.uint8 != null) {\n data_type = \"UINT8\";\n result = params.embeddings.uint8;\n } else if (params.embeddings.float != null) {\n data_type = \"FLOAT32\";\n result = params.embeddings.float;\n }\n \n if (result == null) {\n return \"Invalid embedding result\";\n }\n \n def embedding_list = new StringBuilder(\"[\");\n \n for (int m=0; m - - Table of contents - - {: .text-delta } -- TOC -{:toc} - - ---- - ## Create a query-level monitor -Query-level monitors run the query and check whether or not the results should trigger an alert. Query-level monitors can only trigger one alert at a time. For more information about query-level monitors and bucket-level monitors, see [Creating monitors]({{site.url}}{{site.baseurl}}/monitoring-plugins/alerting/monitors/). +Query-level monitors run the query and determine whether or not the results should trigger an alert. Query-level monitors can only trigger one alert at a time. For more information about query-level and bucket-level monitors, see [Creating monitors]({{site.url}}{{site.baseurl}}/monitoring-plugins/alerting/monitors/). #### Example request - ```json POST _plugins/_alerting/monitors { @@ -92,9 +78,11 @@ POST _plugins/_alerting/monitors }] } ``` +{% include copy-curl.html %} -If you use a custom webhook for your destination and need to embed JSON in the message body, be sure to escape your quotes: +If you use a custom webhook for your destination and need to embed JSON in the message body, be sure to escape the quotation marks: + ```json { "message_template": { @@ -102,13 +90,14 @@ If you use a custom webhook for your destination and need to embed JSON in the m } } ``` +{% include copy-curl.html %} + Optionally, to specify a backend role, you can add the `rbac_roles` parameter and backend role names to the bottom of your create monitor request. +The following request creates a query-level monitor and provides two backend roles, `role1` and `role2`. The section at the bottom of the request shows the line that specifies the roles with this syntax: `"rbac_roles": ["role1", "role2"]`. To learn about using backend roles to limit access, see [(Advanced) Limit access by backend role]({{site.url}}{{site.baseurl}}/monitoring-plugins/alerting/security/#advanced-limit-access-by-backend-role). + #### Example request - -The following request creates a query-level monitor and provides two backend roles, `role1` and `role2`. The section at the bottom of the request shows the line that specifies the roles with this syntax: `"rbac_roles": ["role1", "role2"]`. - ```json POST _plugins/_alerting/monitors { @@ -172,11 +161,16 @@ POST _plugins/_alerting/monitors "rbac_roles": ["role1", "role2"] } ``` +{% include copy-curl.html %} -To learn more about using backend roles to limit access, see [(Advanced) Limit access by backend role]({{site.url}}{{site.baseurl}}/monitoring-plugins/alerting/security/#advanced-limit-access-by-backend-role). +
+ + Select to expand example response + + {: .text-delta} + #### Example response - ```json { "_id": "vd5k2GsBlQ5JUWWFxhsP", @@ -253,13 +247,14 @@ To learn more about using backend roles to limit access, see [(Advanced) Limit a } } ``` +{% include copy-curl.html %} -If you want to specify a time zone, you can do so by including a [cron expression]({{site.url}}{{site.baseurl}}/monitoring-plugins/alerting/cron/) with a time zone name in the `schedule` section of your request. +
-The following example creates a monitor that runs at 12:10 PM Pacific Time on the 1st day of every month. -#### Example request +To specify a time zone, you can do so by including a [cron expression]({{site.url}}{{site.baseurl}}/monitoring-plugins/alerting/cron/) with a time zone name in the `schedule` section of your request. The following example creates a monitor that runs at 12:10 PM Pacific Time on the first day of each month. +#### Example request ```json { "type": "monitor", @@ -321,15 +316,18 @@ The following example creates a monitor that runs at 12:10 PM Pacific Time on th }] } ``` +{% include copy-curl.html %} + -For a full list of time zone names, refer to [Wikipedia](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones). The Alerting plugin uses the Java [TimeZone](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/TimeZone.html) class to convert a [`ZoneId`](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/time/ZoneId.html) to a valid time zone. +For a full list of time zone names, see [List of tz database time zones](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones). The Alerting plugin uses the Java [TimeZone](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/TimeZone.html) class to convert a [`ZoneId`](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/time/ZoneId.html) to a valid time zone. --- ## Bucket-level monitors -Bucket-level monitors categorize results into buckets separated by fields. The monitor then runs your script with each bucket's results and evaluates whether to trigger an alert. For more information about bucket-level and query-level monitors, see [Creating monitors]({{site.url}}{{site.baseurl}}/monitoring-plugins/alerting/monitors/). +Bucket-level monitors categorize results into buckets separated by fields. The monitor then runs the script with each bucket's results and evaluates whether to trigger an alert. For more information about bucket-level and query-level monitors, see [Creating monitors]({{site.url}}{{site.baseurl}}/monitoring-plugins/alerting/monitors/). +#### Example request ```json POST _plugins/_alerting/monitors { @@ -444,7 +442,15 @@ POST _plugins/_alerting/monitors ] } ``` +{% include copy-curl.html %} + +
+ + Select to expand example response + + {: .text-delta} + #### Example response ```json { @@ -584,6 +590,12 @@ POST _plugins/_alerting/monitors } } ``` +{% include copy-curl.html %} + +
+ +--- + ## Document-level monitors Introduced 2.0 {: .label .label-purple } @@ -601,17 +613,18 @@ To retrieve any available findings, send a GET request without any path paramete ```json GET /_plugins/_alerting/findings/_search? ``` - +{% include copy-curl.html %} To retrieve metadata for an individual document finding entry, you can search for the finding by its `findingId` as follows: ```json GET /_plugins/_alerting/findings/_search?findingId=gKQhj8WJit3BxjGfiOXC ``` +{% include copy-curl.html %} The response returns the number of individual finding entries in the `total_findings` field. -To get more specific results in a findings search, you can use any of the optional path parameters that are defined in the following table: +To get more specific results in a findings search, you can use any of the optional path parameters defined in the following table. Path parameter | Description | Usage :--- | :--- : :--- @@ -624,10 +637,9 @@ Path parameter | Description | Usage ### Create a document-level monitor -You can create a document-level monitor with a POST request that provides the monitor details in the request body. -At a minimum, you need to provide the following details: specify the queries or combinations by tag with the `inputs` field, a valid trigger condition, and provide the notification message in the `action` field. +You can create a document-level monitor with a POST request that provides the monitor details in the request body. At a minimum, you need to provide the following details: specify the queries or combinations by tag with the `inputs` field, a valid trigger condition, and provide the notification message in the `action` field. -The following table shows the syntax to use for each trigger option: +The following table provides the syntax to use for each trigger option. Trigger options | Definition | Syntax :--- | :--- : :--- @@ -635,10 +647,8 @@ Tag | Creates alerts for documents that match a multiple query with this tag app Query by name | Creates alerts for documents matched or returned by the named query. | `query[name=]` Query by ID | Creates alerts for documents that were returned by the identified query. | `query[id=]` -#### Example request - -The following example shows how to create a document-level monitor: +#### Example request ```json POST _plugins/_alerting/monitors { @@ -722,18 +732,20 @@ POST _plugins/_alerting/monitors } ``` +{% include copy-curl.html %} + ### Limitations If you run a document-level query while the index is getting reindexed, the API response will not return the reindexed results. To get updates, wait until the reindexing process completes, then rerun the query. -{: .tip} -## Update monitor +--- -When updating a monitor, you can optionally include `seq_no` and `primary_term` as URL parameters. If these numbers don't match the existing monitor or the monitor doesn't exist, the Alerting plugin throws an error. OpenSearch increments the version number and the sequence number automatically (see the example response). +## Update monitor -#### Request +When updating a monitor, you can optionally include `seq_no` and `primary_term` as URL parameters. If these numbers do not match the existing monitor or the monitor does not exist, the Alerting plugin throws an error. OpenSearch increments the version number and the sequence number automatically (see the example response). +#### Example request ```json PUT _plugins/_alerting/monitors/ { @@ -839,9 +851,16 @@ PUT _plugins/_alerting/monitors/?if_seq_no=3&if_primary_term=1 "last_update_time": 1551466639295 } ``` +{% include copy-curl.html %} -#### Example response +
+ + Select to expand example response + + {: .text-delta} + +#### Example response ```json { "_id": "Q9aXOmkBC25HCRGmzfw-", @@ -900,20 +919,30 @@ PUT _plugins/_alerting/monitors/?if_seq_no=3&if_primary_term=1 } } ``` +{% include copy-curl.html %} +
--- ## Get monitor -#### Request +Retrieve the details of a specific monitor using the following request. +#### Example request ``` GET _plugins/_alerting/monitors/ ``` +{% include copy-curl.html %} -#### Example response +
+ + Select to expand example response + + {: .text-delta} + +#### Example response ```json { "_id": "Q9aXOmkBC25HCRGmzfw-", @@ -972,7 +1001,9 @@ GET _plugins/_alerting/monitors/ } } ``` +{% include copy-curl.html %} +
--- @@ -980,17 +1011,23 @@ GET _plugins/_alerting/monitors/ Returns statistics about the alerting feature. Use `_plugins/_alerting/stats` to find node IDs and metrics. Then you can drill down using those values. -#### Request - +#### Example request ```json GET _plugins/_alerting/stats GET _plugins/_alerting/stats/ GET _plugins/_alerting//stats GET _plugins/_alerting//stats/ ``` +{% include copy-curl.html %} -#### Example response +
+ + Select to expand example response + + {: .text-delta} + +#### Example response ```json { "_nodes": { @@ -1161,20 +1198,30 @@ GET _plugins/_alerting//stats/ } } ``` +{% include copy-curl.html %} +
--- ## Delete monitor -#### Request +Delete a monitor using the following request. +#### Example request ``` DELETE _plugins/_alerting/monitors/ ``` +{% include copy-curl.html %} -#### Example response +
+ + Select to expand example response + + {: .text-delta} + +#### Example response ```json { "_index": ".opensearch-scheduled-jobs", @@ -1191,14 +1238,17 @@ DELETE _plugins/_alerting/monitors/ "_primary_term": 1 } ``` +{% include copy-curl.html %} +
--- ## Search monitors -#### Request +Query and retrieve information about existing monitors based on specific criteria, such as the monitor name, using the following request. +#### Example request ```json GET _plugins/_alerting/monitors/_search { @@ -1209,9 +1259,16 @@ GET _plugins/_alerting/monitors/_search } } ``` +{% include copy-curl.html %} -#### Example response +
+ + Select to expand example response + + {: .text-delta} + +#### Example response ```json { "took": 17, @@ -1288,7 +1345,9 @@ GET _plugins/_alerting/monitors/_search } } ``` +{% include copy-curl.html %} +
--- @@ -1296,15 +1355,20 @@ GET _plugins/_alerting/monitors/_search You can add the optional `?dryrun=true` parameter to the URL to show the results of a run without actions sending any message. - -#### Request - +#### Example request ```json POST _plugins/_alerting/monitors//_execute ``` +{% include copy-curl.html %} -#### Example response +
+ + Select to expand example response + + {: .text-delta} + +#### Example response ```json { "monitor_name": "logs", @@ -1321,12 +1385,15 @@ POST _plugins/_alerting/monitors//_execute } } ``` +{% include copy-curl.html %} + +
--- ## Get alerts -Returns an array of all alerts. +Return an array of all alerts. #### Path parameters @@ -1345,14 +1412,20 @@ The following table lists the available path parameters. All path parameters are | `monitorId` | String | Filters by monitor ID. | `workflowIds` | String | Allows for monitoring the status of chained alerts from multiple workflows within a single dashboard. Available in OpenSearch 2.9 or later. -#### Request - +#### Example request ```json GET _plugins/_alerting/monitors/alerts ``` +{% include copy-curl.html %} + -#### Response +
+ + Select to expand example response + + {: .text-delta} +#### Example response ```json { "alerts": [ @@ -1406,25 +1479,34 @@ GET _plugins/_alerting/monitors/alerts "totalAlerts": 1 } ``` +{% include copy-curl.html %} + +
--- ## Acknowledge alert -[After getting your alerts](#get-alerts), you can acknowledge any number of active alerts in one call. If the alert is already in an ERROR, COMPLETED, or ACKNOWLEDGED state, it appears in the `failed` array. - - -#### Request +[After getting your alerts](#get-alerts), you can acknowledge any number of active alerts in one call. If the alert is already in an `ERROR`, `COMPLETED`, or `ACKNOWLEDGED` state, it appears in the `failed` array. +#### Example request ```json POST _plugins/_alerting/monitors//_acknowledge/alerts { "alerts": ["eQURa3gBKo1jAh6qUo49"] } ``` +{% include copy-curl.html %} -#### Example response +
+ + Select to expand example response + + {: .text-delta} + + +#### Example response ```json { "success": [ @@ -1433,13 +1515,17 @@ POST _plugins/_alerting/monitors//_acknowledge/alerts "failed": [] } ``` +{% include copy-curl.html %} + +
--- ## Create destination -#### Requests +Define and configure various destinations for receiving alert notifications using the following request. These destinations can be of different types, such as Slack, custom webhooks, or email, and are used to specify where and how alerts should be delivered. +#### Example request ```json POST _plugins/_alerting/destinations { @@ -1489,9 +1575,16 @@ POST _plugins/_alerting/destinations // The email_account_id and email_group_id will be the document IDs of the email_account and email_group you have created. ``` +{% include copy-curl.html %} -#### Example response +
+ + Select to expand example response + + {: .text-delta} + +#### Example response ```json { "_id": "nO-yFmkB8NzS6aXjJdiI", @@ -1508,16 +1601,17 @@ POST _plugins/_alerting/destinations } } ``` +{% include copy-curl.html %} +
--- ## Update destination -When updating a destination, you can optionally include `seq_no` and `primary_term` as URL parameters. If these numbers don't match the existing destination or the destination doesn't exist, the Alerting plugin throws an error. OpenSearch increments the version number and the sequence number automatically (see the example response). - -#### Request +When updating a destination, you can optionally include `seq_no` and `primary_term` as URL parameters. If these numbers do not match the existing destination or the destination doesn't exist, the Alerting plugin throws an error. OpenSearch increments the version number and the sequence number automatically (see the example response). +#### Example request ```json PUT _plugins/_alerting/destinations/ { @@ -1537,9 +1631,16 @@ PUT _plugins/_alerting/destinations/?if_seq_no=3&if_primary_term } } ``` +{% include copy-curl.html %} -#### Example response +
+ + Select to expand example response + + {: .text-delta} + +#### Example response ```json { "_id": "pe-1FmkB8NzS6aXjqvVY", @@ -1556,22 +1657,30 @@ PUT _plugins/_alerting/destinations/?if_seq_no=3&if_primary_term } } ``` +{% include copy-curl.html %} +
--- ## Get destination -Retrieve one destination. - -#### Requests +Retrieve one destination using the following request. +#### Example request ```json GET _plugins/_alerting/destinations/ ``` +{% include copy-curl.html %} -#### Example response +
+ + Select to expand example response + + {: .text-delta} + +#### Example response ```json { "totalDestinations": 1, @@ -1601,22 +1710,30 @@ GET _plugins/_alerting/destinations/ ] } ``` +{% include copy-curl.html %} +
--- ## Get destinations -Retrieve all destinations. - -#### Requests +Retrieve all destinations using the following request. +#### Example request ```json GET _plugins/_alerting/destinations ``` +{% include copy-curl.html %} -#### Example response +
+ + Select to expand example response + + {: .text-delta} + +#### Example response ```json { "totalDestinations": 1, @@ -1646,20 +1763,30 @@ GET _plugins/_alerting/destinations ] } ``` +{% include copy-curl.html %} +
--- ## Delete destination -#### Request +Remove a specific destination from the alerting system using the following request. +#### Example request ``` DELETE _plugins/_alerting/destinations/ ``` +{% include copy-curl.html %} -#### Example response +
+ + Select to expand example response + + {: .text-delta} + +#### Example response ```json { "_index": ".opendistro-alerting-config", @@ -1677,11 +1804,17 @@ DELETE _plugins/_alerting/destinations/ "_primary_term": 1 } ``` +{% include copy-curl.html %} + +
+ --- ## Create email account -#### Request +Set up a new email account for sending alert notifications using the following request. + +#### Example request ```json POST _plugins/_alerting/destinations/email_accounts { @@ -1692,6 +1825,14 @@ POST _plugins/_alerting/destinations/email_accounts "method": "ssl" } ``` +{% include copy-curl.html %} + + +
+ + Select to expand example response + + {: .text-delta} #### Example response ```json @@ -1710,12 +1851,15 @@ POST _plugins/_alerting/destinations/email_accounts } } ``` +{% include copy-curl.html %} + +
## Update email account When updating an email account, you can optionally include `seq_no` and `primary_term` as URL parameters. If these numbers don't match the existing email account or the email account doesn't exist, the Alerting plugin throws an error. OpenSearch increments the version number and the sequence number automatically (see the example response). -#### Request +#### Example request ```json PUT _plugins/_alerting/destinations/email_accounts/ { @@ -1735,6 +1879,15 @@ PUT _plugins/_alerting/destinations/email_accounts/?if_seq_no= "method": "ssl" } ``` +{% include copy-curl.html %} + + +
+ + Select to expand example response + + {: .text-delta} + #### Example response ```json { @@ -1752,10 +1905,15 @@ PUT _plugins/_alerting/destinations/email_accounts/?if_seq_no= } } ``` +{% include copy-curl.html %} + +
## Get email account -#### Request +Retrieve the details of a specific email account configured for alerting purposes using the following request. + +#### Example request ```json GET _plugins/_alerting/destinations/email_accounts/ { @@ -1766,6 +1924,15 @@ GET _plugins/_alerting/destinations/email_accounts/ "method": "ssl" } ``` +{% include copy-curl.html %} + + +
+ + Select to expand example response + + {: .text-delta} + #### Example response ```json { @@ -1783,15 +1950,28 @@ GET _plugins/_alerting/destinations/email_accounts/ } } ``` +{% include copy-curl.html %} + +
## Delete email account -#### Request +Remove an existing email account configuration from the alerting system using the following request. + +#### Example request ``` DELETE _plugins/_alerting/destinations/email_accounts/ ``` -#### Example response +{% include copy-curl.html %} + +
+ + Select to expand example response + + {: .text-delta} + +#### Example response ```json { "_index" : ".opendistro-alerting-config", @@ -1809,11 +1989,15 @@ DELETE _plugins/_alerting/destinations/email_accounts/ "_primary_term" : 2 } ``` +{% include copy-curl.html %} + +
## Search email account -#### Request +Retrieve information about the configured email accounts used for email-based alerting using the following request. +#### Example request ```json POST _plugins/_alerting/destinations/email_accounts/_search { @@ -1829,9 +2013,16 @@ POST _plugins/_alerting/destinations/email_accounts/_search } } ``` +{% include copy-curl.html %} -#### Example response +
+ + Select to expand example response + + {: .text-delta} + +#### Example response ```json { "took" : 8, @@ -1873,13 +2064,17 @@ POST _plugins/_alerting/destinations/email_accounts/_search } } ``` +{% include copy-curl.html %} + +
--- ## Create email group -#### Request +Define a new group of email recipients for alerts using the following request. +#### Example request ```json POST _plugins/_alerting/destinations/email_groups { @@ -1889,9 +2084,16 @@ POST _plugins/_alerting/destinations/email_groups }] } ``` +{% include copy-curl.html %} -#### Example response +
+ + Select to expand example response + + {: .text-delta} + +#### Example response ```json { "_id" : "email_group_id", @@ -1909,13 +2111,15 @@ POST _plugins/_alerting/destinations/email_groups } } ``` +{% include copy-curl.html %} + +
## Update email group When updating an email group, you can optionally include `seq_no` and `primary_term` as URL parameters. If these numbers don't match the existing email group or the email group doesn't exist, the Alerting plugin throws an error. OpenSearch increments the version number and the sequence number automatically (see the example response). -#### Request - +#### Example request ```json PUT _plugins/_alerting/destinations/email_groups/ { @@ -1933,8 +2137,16 @@ PUT _plugins/_alerting/destinations/email_groups/?if_seq_no=16&i }] } ``` -#### Example response +{% include copy-curl.html %} + +
+ + Select to expand example response + + {: .text-delta} + +#### Example response ```json { "_id" : "email_group_id", @@ -1952,10 +2164,15 @@ PUT _plugins/_alerting/destinations/email_groups/?if_seq_no=16&i } } ``` +{% include copy-curl.html %} + +
## Get email group -#### Request +Retrieve the details of a specific email group destination using the following request, passing the ID of the email group you want to fetch. + +#### Example request ```json GET _plugins/_alerting/destinations/email_groups/ { @@ -1965,8 +2182,16 @@ GET _plugins/_alerting/destinations/email_groups/ }] } ``` -#### Example response +{% include copy-curl.html %} + +
+ + Select to expand example response + + {: .text-delta} + +#### Example response ```json { "_id" : "email_group_id", @@ -1984,15 +2209,28 @@ GET _plugins/_alerting/destinations/email_groups/ } } ``` +{% include copy-curl.html %} + +
## Delete email group -#### Request +Remove an existing email group from the list of destinations for alerts using the following request. + +#### Example request ``` DELETE _plugins/_alerting/destinations/email_groups/ ``` -#### Example response +{% include copy-curl.html %} + +
+ + Select to expand example response + + {: .text-delta} + +#### Example response ```json { "_index" : ".opendistro-alerting-config", @@ -2010,11 +2248,15 @@ DELETE _plugins/_alerting/destinations/email_groups/ "_primary_term" : 2 } ``` +{% include copy-curl.html %} + +
## Search email group -#### Request +Query and retrieve information about existing email groups used for alerting purposes, enabling you to filter and sort the results based on various criteria. An example is shown in the following request. +#### Example request ```json POST _plugins/_alerting/destinations/email_groups/_search { @@ -2030,9 +2272,16 @@ POST _plugins/_alerting/destinations/email_groups/_search } } ``` +{% include copy-curl.html %} -#### Example response +
+ + Select to expand example response + + {: .text-delta} + +#### Example response ```json { "took" : 7, @@ -2075,4 +2324,203 @@ POST _plugins/_alerting/destinations/email_groups/_search } } ``` ---- +{% include copy-curl.html %} + +
+ +## Create comment +This is an experimental feature and is not recommended for use in a production environment. +{: .warning} + +Add comments to a specific alert, providing additional context or notes related to that alert, using the following request. + +#### Example request +```json +POST _plugins/_alerting/comments/ +{ + "content": "sample comment" +} +``` +{% include copy-curl.html %} + + +
+ + Select to expand example response + + {: .text-delta} + +#### Example response +```json +{ + "_id": "0U6aBJABVWc3FrmWer9s", + "_seq_no": 7, + "_primary_term": 2, + "comment": { + "entity_id": "vCZkA5ABWTh3kzuBEL_9", + "entity_type": "alert", + "content": "sample comment", + "created_time": 1718064151148, + "last_updated_time": null, + "user": "admin" + } +} +``` +{% include copy-curl.html %} + +
+ +## Update comment +This is an experimental feature and is not recommended for use in a production environment. +{: .warning} + +Modify the content of a previously added comment associated with an alert using the following request. + +#### Example request + +```json +PUT _plugins/_alerting/comments/ +{ + "content": "sample updated comment" +} +``` +{% include copy-curl.html %} + + +
+ + Select to expand example response + + {: .text-delta} + +#### Example response +```json +{ + "_id": "0U6aBJABVWc3FrmWer9s", + "_seq_no": 8, + "_primary_term": 3, + "comment": { + "entity_id": "vCZkA5ABWTh3kzuBEL_9", + "entity_type": "alert", + "content": "sample updated comment", + "created_time": 1718064151148, + "last_updated_time": 1718064745485, + "user": "admin" + } +} +``` +{% include copy-curl.html %} + +
+ +## Search comment +This is an experimental feature and is not recommended for use in a production environment. +{: .warning} + +Query and retrieve existing comments associated with alerts using the following request. + +#### Example request +```json +GET _plugins/_alerting/comments/_search +{ + "query": { + "match_all" : {} + } +} +``` +{% include copy-curl.html %} + + +
+ + Select to expand example response + + {: .text-delta} + +#### Example response +```json +{ + "took": 14, + "timed_out": false, + "_shards": { + "total": 1, + "successful": 1, + "skipped": 0, + "failed": 0 + }, + "hits": { + "total": { + "value": 2, + "relation": "eq" + }, + "max_score": 1, + "hits": [ + { + "_index": ".opensearch-alerting-comments-history-2024.06.10-1", + "_id": "xE5tBJABVWc3FrmWRL5i", + "_version": 1, + "_seq_no": 3, + "_primary_term": 2, + "_score": 1, + "_source": { + "entity_id": "vCZkA5ABWTh3kzuBEL_9", + "entity_type": "alert", + "content": "a different sample comment", + "created_time": 1718061188191, + "last_updated_time": null, + "user": "admin" + } + }, + { + "_index": ".opensearch-alerting-comments-history-2024.06.10-1", + "_id": "0U6aBJABVWc3FrmWer9s", + "_version": 3, + "_seq_no": 9, + "_primary_term": 3, + "_score": 1, + "_source": { + "entity_id": "vCZkA5ABWTh3kzuBEL_9", + "entity_type": "alert", + "content": "sample updated comment", + "created_time": 1718064151148, + "last_updated_time": 1718064745485, + "user": "admin" + } + } + ] + } +} +``` +{% include copy-curl.html %} + +
+ +## Delete comment +This is an experimental feature and is not recommended for use in a production environment. +{: .warning} + +Remove a specific comment associated with an alert using the following request. + +#### Example request +```json +DELETE _plugins/_alerting/comments/ +``` +{% include copy-curl.html %} + + +
+ + Select to expand example response + + {: .text-delta} + +#### Example response +```json +{ + "_id": "0U6aBJABVWc3FrmWer9s" +} +``` +{% include copy-curl.html %} + +
+ diff --git a/_observing-your-data/alerting/comments.md b/_observing-your-data/alerting/comments.md new file mode 100644 index 0000000000..fb0630685c --- /dev/null +++ b/_observing-your-data/alerting/comments.md @@ -0,0 +1,26 @@ +--- +layout: default +title: Adding comments +nav_order: 35 +parent: Alerting +has_children: false +redirect_from: + - /monitoring-plugins/alerting/comments/ +--- + +# Adding comments + +This is an experimental feature and is not recommended for use in a production environment. For updates on the progress of the feature or if you want to leave feedback, see the associated [GitHub issue](https://github.com/opensearch-project/OpenSearch-Dashboards/issues/6999). +{: .warning} + +When an alert is generated, add comments to share information about its root cause and facilitate resolution. Comments are enabled by setting `plugins.alerting.comments_enabled` to `true` using the [`cluster/settings` API]({{site.url}}{{site.baseurl}}/observing-your-data/alerting/settings/). + +Comments can be accessed through the alerts table view by selecting the comment icon within an alert's row. From there, comments can be added, edited, or deleted. An Alerting Comments API is also available for programmatic comment management. For more information, see [Alerting API]({{site.url}}{{site.baseurl}}/observing-your-data/alerting/api/). + +## Viewing comment authors + +If the Security plugin is installed, then the comment's author is displayed. Otherwise, `Unknown` is displayed. + +## Assigning permissions + +Comment permissions are determined by the backend roles associated with the alert. These backend roles are inherited from the monitor that generated the alert. For more information about how to limit access based on backend roles, see [Limit access by backend role]({{site.url}}{{site.baseurl}}/observing-your-data/alerting/security/#advanced-limit-access-by-backend-role). diff --git a/_observing-your-data/alerting/cron.md b/_observing-your-data/alerting/cron.md index b37d13e576..11a91609dd 100644 --- a/_observing-your-data/alerting/cron.md +++ b/_observing-your-data/alerting/cron.md @@ -63,4 +63,4 @@ Every three hours on the first day of every other month: ## API -For an example of how to use a custom cron expression in an API call, see the [create monitor API operation]({{site.url}}{{site.baseurl}}/monitoring-plugins/alerting/api#request-1). +For an example of how to use a custom cron expression in an API call, see the [create monitor API operation]({{site.url}}{{site.baseurl}}/monitoring-plugins/alerting/api/#example-request-2). diff --git a/_observing-your-data/alerting/index.md b/_observing-your-data/alerting/index.md index a78c4cb93f..2b5ced8d1c 100644 --- a/_observing-your-data/alerting/index.md +++ b/_observing-your-data/alerting/index.md @@ -45,7 +45,7 @@ Deleted | The monitor or trigger associated with this alert was deleted while th You can follow these basic steps to create an alert monitor: 1. In the **OpenSearch Plugins** main menu, choose **Alerting**. -1. Choose **Create monitor**. See [Monitors]({{site.url}}{{site.baseurl}}/observing-your-data/notifications/index/) for more information about the monitor types. +1. Choose **Create monitor**. See [Monitors]({{site.url}}{{site.baseurl}}/observing-your-data/alerting/monitors/) for more information about the monitor types. 1. Enter the **Monitor details**, including monitor type, method, and schedule. 1. Select a data source from the dropdown list. 1. Define the metrics in the Query section. @@ -53,4 +53,4 @@ You can follow these basic steps to create an alert monitor: 1. Add an action. See [Actions]({{site.url}}{{site.baseurl}}/observing-your-data/alerting/actions/) for more information about actions. 1. Select **Create**. -Learn more about creating specific monitor types in their respective documentation. \ No newline at end of file +Learn more about creating specific monitor types in their respective documentation. diff --git a/_observing-your-data/alerting/per-cluster-metrics-monitors.md b/_observing-your-data/alerting/per-cluster-metrics-monitors.md index 99984a16a5..baea9c626b 100644 --- a/_observing-your-data/alerting/per-cluster-metrics-monitors.md +++ b/_observing-your-data/alerting/per-cluster-metrics-monitors.md @@ -115,6 +115,9 @@ The `script` parameter points the `source` to the Painless script `for (cluster ``` The dashboards interface supports the selection of clusters to be monitored and the desired API. A view of the interface is shown in the following image. +The following [permissions]({{site.url}}{{site.baseurl}}/security/access-control/permissions/) are required in order to create a cross-cluster monitor through the dashboards UI: `cluster:admin/opensearch/alerting/remote/indexes/get`, `indices:admin/resolve/index`, `cluster:monitor/health`, and `indices:admin/mappings/get`. +{: .note} + Cluster metrics monitor ### Limitations diff --git a/_observing-your-data/alerting/per-query-bucket-monitors.md b/_observing-your-data/alerting/per-query-bucket-monitors.md index d4fe0ff9d7..cb08c49478 100644 --- a/_observing-your-data/alerting/per-query-bucket-monitors.md +++ b/_observing-your-data/alerting/per-query-bucket-monitors.md @@ -15,6 +15,9 @@ Per bucket monitors are a type of alert monitor that can be used to identify and Both monitor types support querying remote indexes using the same `cluster-name:index-name` pattern used by [cross-cluster search](https://opensearch.org/docs/latest/security/access-control/cross-cluster-search/) or by using OpenSearch Dashboards 2.12 or later. +The following [permissions]({{site.url}}{{site.baseurl}}/security/access-control/permissions/) are required in order to create a cross-cluster monitor through the dashboards UI: `cluster:admin/opensearch/alerting/remote/indexes/get`, `indices:admin/resolve/index`, `cluster:monitor/health`, and `indices:admin/mappings/get`. +{: .note} + Cluster metrics monitor ## Creating a per query or per bucket monitor diff --git a/_observing-your-data/alerting/settings.md b/_observing-your-data/alerting/settings.md index c50636b3ae..c7eefe528b 100644 --- a/_observing-your-data/alerting/settings.md +++ b/_observing-your-data/alerting/settings.md @@ -51,12 +51,20 @@ Setting | Default | Description `plugins.alerting.alert_history_max_age` | 30d | The oldest document to store in the `.opendistro-alert-history-` index before creating a new index. If the number of alerts in this time period does not exceed `alert_history_max_docs`, alerting creates one history index per period (e.g. one index every 30 days). `plugins.alerting.alert_history_max_docs` | 1000 | The maximum number of alerts to store in the `.opendistro-alert-history-` index before creating a new index. `plugins.alerting.alert_history_enabled` | true | Whether to create `.opendistro-alerting-alert-history-` indexes. -`plugins.alerting.alert_history_retention_period` | 60d | The amount of time to keep history indexes before automatically deleting them. +`plugins.alerting.alert_history_retention_period` | 60d | The amount of time to store history indexes before automatically deleting them. `plugins.alerting.destination.allow_list` | ["chime", "slack", "custom_webhook", "email", "test_action"] | The list of allowed destinations. If you don't want to allow users to a certain type of destination, you can remove it from this list, but we recommend leaving this setting as-is. `plugins.alerting.filter_by_backend_roles` | "false" | Restricts access to monitors by backend role. See [Alerting security]({{site.url}}{{site.baseurl}}/monitoring-plugins/alerting/security/). -`plugins.alerting.remote_monitoring_enabled` | "false" | Toggles whether cluster metrics monitors support executing against remote clusters. +`plugins.alerting.cross_cluster_monitoring_enabled` | "false" | Toggles whether cluster metrics monitors support running against remote clusters. `plugins.scheduled_jobs.sweeper.period` | 5m | The alerting feature uses its "job sweeper" component to periodically check for new or updated jobs. This setting is the rate at which the sweeper checks to see if any jobs (monitors) have changed and need to be rescheduled. `plugins.scheduled_jobs.sweeper.page_size` | 100 | The page size for the sweeper. You shouldn't need to change this value. `plugins.scheduled_jobs.sweeper.backoff_millis` | 50ms | The amount of time the sweeper waits between retries---increases exponentially after each failed retry. `plugins.scheduled_jobs.sweeper.retry_count` | 3 | The total number of times the sweeper should retry before throwing an error. `plugins.scheduled_jobs.request_timeout` | 10s | The timeout for the request that sweeps shards for jobs. +`plugins.alerting.comments_enabled` | `false` | Enables or disables comments for the Alerting plugin. +`plugins.alerting.comments_history_max_docs` | 1000 | The maximum number of comments to store in the `.opensearch-alerting-comments-history-` index before creating a new index. +`plugins.alerting.comments_history_max_age` | 30d | The oldest document to store in an `.opensearch-alerting-comments-history-` index before creating a new one. If the number of comments in the specified time period does not exceed `comments_history_max_docs`, then 1 index is created per period (for example, 1 every 30 days). +`plugins.alerting.comments_history_rollover_period` | 12h | How often to determine whether the `.opensearch-alerting-comments-history-write` alias should roll over to a new index and delete old comment history indexes. +`plugins.alerting.comments_history_retention_period` | 60d | The amount of time to keep comment history indexes before automatic deletion. +`plugins.alerting.max_comment_character_length` | 2000 | The maximum character length of a comment. +`plugins.alerting.max_comments_per_alert` | 500 | The maximum number of comments that can be posted on an alert. +`plugins.alerting.max_comments_per_notification` | 3 | The maximum number of comments per alert to include in the `ctx` Mustache template variable for alert notifications. diff --git a/_observing-your-data/alerting/triggers.md b/_observing-your-data/alerting/triggers.md index 06b49f17de..0cbc5d6ea5 100644 --- a/_observing-your-data/alerting/triggers.md +++ b/_observing-your-data/alerting/triggers.md @@ -159,6 +159,7 @@ Variable | Data type | Description ##### Mustache template example +{% raw %} ```groovy Alerts: {{#ctx.alerts}} @@ -171,6 +172,7 @@ Alerts: {{/associated_queries}} {{/ctx.alerts}} ``` +{% endraw %} #### Associated query variables @@ -185,6 +187,7 @@ Variable | Data type | Description The `_source` object in this example is based on the `opensearch_dashboards_sample_data_ecommerce` index available in OpenSearch Dashboards. In this example, the message template is accessing the `ctx.alerts` variable of a per document monitor. {: .note} +{% raw %} ```groovy Alerts {{#ctx.alerts}} @@ -199,4 +202,5 @@ Alerts ----------------- {{/sample_documents}} {{/ctx.alerts}} -``` \ No newline at end of file +``` +{% endraw %} \ No newline at end of file diff --git a/_observing-your-data/event-analytics.md b/_observing-your-data/event-analytics.md index b8fe72964c..a41d55c2ff 100644 --- a/_observing-your-data/event-analytics.md +++ b/_observing-your-data/event-analytics.md @@ -3,7 +3,7 @@ layout: default title: Event analytics nav_order: 20 redirect_from: - - /observing-your-data/event-analytics/ + - /observability-plugin/event-analytics/ --- # Event analytics diff --git a/_observing-your-data/log-analytics.md b/_observing-your-data/log-analytics.md deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/_observing-your-data/prometheusmetrics.md b/_observing-your-data/prometheusmetrics.md index 592d851ab5..85448ca358 100644 --- a/_observing-your-data/prometheusmetrics.md +++ b/_observing-your-data/prometheusmetrics.md @@ -1,28 +1,37 @@ --- layout: default -title: Metrics analytics +title: Metric analytics nav_order: 40 -redirect_from: - - /observing-your-data/prometheusmetrics/ --- -# Metrics analytics +# Metric analytics Introduced 2.4 {: .label .label-purple } -Starting with OpenSearch 2.4, you can ingest and visualize metric data from log data aggregated within OpenSearch, allowing you to analyze and correlate data across logs, traces, and metrics. Previously, you could ingest and visualize only logs and traces from your monitored environments. With this feature, you can observe your digital assets with more granularity, gain deeper insight into the health of your infrastructure, and better inform your root cause analysis. +With the release of OpenSearch 2.4, you can now ingest and visualize metric data stored directly in OpenSearch using the **Metrics** tool. This equips you with tools to analyze and correlate data across logs, traces, and metrics. -The following image shows the process of ingesting metrics from Prometheus and visualizing them in a dashboard. +Before the introduction of this feature, you could only ingest and visualize logs and traces from your monitored environments. With the **Metrics** tool, you can now observe your digital assets with more granularity, gain deeper insight into the health of your infrastructure, and better inform your root cause analysis. -![Prometheus and Metrics]({{site.url}}{{site.baseurl}}/images/metrics/metricsgif.gif) +The **Metrics** tool offers federated visualization capabilities in addition to the following: -## Configuring a data source connection from Prometheus to OpenSearch + - An OpenSearch cluster containing an [OpenTelemetry (OTel)-compatible metrics index](https://github.com/opensearch-project/opensearch-catalog/tree/main/docs/schema/observability/metrics) with OTel-based signals. See [What is OpenTelemetry?](https://opentelemetry.io/docs/what-is-opentelemetry/) for an overview of OTel. + - An OpenSearch cluster containing a [Prometheus data source](https://github.com/opensearch-project/sql/blob/main/docs/dev/datasource-prometheus.md) connected to a Prometheus server. -You can view metrics collected from Prometheus in OpenSearch Dashboards by first creating a connection from [Prometheus](https://prometheus.io/) to OpenSearch using the SQL plugin. +The following image displays the flow for retrieving metrics from Prometheus and displaying them on a visualization dashboard. -To configure a connection to Prometheus, you can use the `_datasources` configuration API endpoint. +Prometheus data source -The following example request configures a Prometheus data source with no authentication: +The following image displays an observability dashboard that visualizes metric data from the OpenSearch index using OTel queries. + +OTel data source + +--- + +## Configuring Prometheus to send metric data to OpenSearch + +You must first create a connection from [Prometheus](https://prometheus.io/) to OpenSearch using the [SQL plugin](https://github.com/opensearch-project/sql). You can then configure a connection to Prometheus by using the `_datasources` API endpoint. + +The following example shows a request that configures a Prometheus data source without any authentication: ```json POST _plugins/_query/_datasources @@ -34,8 +43,9 @@ POST _plugins/_query/_datasources } } ``` +{% include copy-curl.html %} -The following example request configures a Prometheus data source with AWS SigV4 authentication: +The following example shows how to configure a Prometheus data source using AWS Signature Version 4 authentication: ```json POST _plugins/_query/_datasources @@ -51,48 +61,143 @@ POST _plugins/_query/_datasources } } ``` +{% include copy-curl.html %} + +After configuring the connection, you can view Prometheus metrics in OpenSearch Dashboards by going to the **Observability** > **Metrics** page, as shown in the following image. + +Prometheus metrics displayed on a dashboard + +### Developer resources + +See the following developer resources for sample code, articles, tutorials, and API references: + +* [Datasource Settings](https://github.com/opensearch-project/sql/blob/main/docs/user/ppl/admin/datasources.rst), which contains information about authentication and authorization of data source APIs. +* [Prometheus Connector](https://github.com/opensearch-project/sql/blob/main/docs/user/ppl/admin/connectors/prometheus_connector.rst), which contains configuration information. +* [Simple Schema for Observability](https://github.com/opensearch-project/opensearch-catalog/tree/main/docs/schema/observability), which contains information about the OTel schema and ingest pipeline. +* [OTel Metrics Source](https://github.com/opensearch-project/data-prepper/tree/main/data-prepper-plugins/otel-metrics-source), which contains information about the Data Prepper metrics pipeline and ingestion. + +--- + +## Experimenting with OpenTelemetry Metrics in the OpenSearch demo environment + +The OpenSearch [`opentelemetry-demo` repository](https://github.com/opensearch-project/opentelemetry-demo) provides a practical demonstration of collecting, processing, and visualizing metric data through **OpenTelemetry Metrics** from OpenTelemetry and using the **Metrics** tool in OpenSearch Dashboards. + +### Visualizing OTel metrics in OpenSearch + +To visualize OTel metric data in OpenSearch, follow these steps: + +1. Install the [`opentelemetry-demo` repository](https://github.com/opensearch-project/opentelemetry-demo). See the [Getting Started](https://github.com/opensearch-project/opentelemetry-demo/blob/main/tutorial/GettingStarted.md) guide for instructions. +2. Collect the OTel signals, including metric signals. See the [OTel Collector](https://opentelemetry.io/docs/collector/) guide for instructions. +3. Configure the OTel pipeline to emit metric signals. See the [OTel Collector Pipeline](https://github.com/opensearch-project/opentelemetry-demo/tree/main/src/otelcollector) guide for instructions. + +#### Example YAML config file + +```yaml + service: + extensions: [basicauth/client] + pipelines: + traces: + receivers: [otlp] + processors: [batch] + exporters: [otlp, debug, spanmetrics, otlp/traces, opensearch/traces] + metrics: + receivers: [otlp, spanmetrics] + processors: [filter/ottl, transform, batch] + exporters: [otlphttp/prometheus, otlp/metrics, debug] + logs: + receivers: [otlp] + processors: [batch] + exporters: [otlp/logs, opensearch/logs, debug] +``` +{% include copy-curl.html %} + +4. Configure the [Data Prepper pipeline](https://github.com/opensearch-project/opentelemetry-demo/blob/main/src/dataprepper/pipelines.yaml) to emit the collected metric signals into the OpenSearch metrics index. + +#### Example YAML config file + +```yaml + otel-metrics-pipeline: + workers: 8 + delay: 3000 + source: + otel_metrics_source: + health_check_service: true + ssl: false + buffer: + bounded_blocking: + buffer_size: 1024 # max number of records the buffer accepts + batch_size: 1024 # max number of records the buffer drains after each read + processor: + - otel_metrics: + calculate_histogram_buckets: true + calculate_exponential_histogram_buckets: true + exponential_histogram_max_allowed_scale: 10 + flatten_attributes: false + sink: + - opensearch: + hosts: ["https://opensearch-node1:9200"] + username: "admin" + password: "my_%New%_passW0rd!@#" + insecure: true + index_type: custom + template_file: "templates/ss4o_metrics.json" + index: ss4o_metrics-otel-%{yyyy.MM.dd} + bulk_size: 4 +``` +{% include copy-curl.html %} -After configuring the connection from Prometheus to OpenSearch, Prometheus metrics are displayed in Dashboards in the **Observability** > **Metrics analytics** window, as shown in the following image. +5. Ingest metric data into OpenSearch. As the demo starts generating data, the metric signals will be added to the OpenSearch index that supports the OpenTelemetry Metrics schema format. +6. On the **Metrics** page, choose `Otel-Index` from the **Data sources** dropdown menu and `Simple Schema for Observability Index` from the **OTel index** dropdown menu. A visualization is displayed, as shown in the following image. -![Metrics UI example 1]({{site.url}}{{site.baseurl}}/images/metrics/metrics1.png) +OTel metrics dashboard -* For more information about authentication and authorization of data source APIs, see [data source documentation on GitHub](https://github.com/opensearch-project/sql/blob/main/docs/user/ppl/admin/datasources.rst). -* For more information about the Prometheus connector, see the [Prometheus Connector](https://github.com/opensearch-project/sql/blob/main/docs/user/ppl/admin/connectors/prometheus_connector.rst) GitHub page. +--- -## Creating visualizations based on metrics +## Visualizing metrics in remote clusters +Introduced 2.14 +{: .label .label-purple } + +You can view metrics from remote OpenSearch clusters by using the **Metrics** tool. Select the database icon on the upper-right toolbar and choose a cluster from the **DATA SOURCES** dropdown menu, as shown in the following image. You can switch from a local cluster to a remote cluster. + +Switching clusters using the Metrics analytics tool + +You can also view metric visualizations from other sources alongside local metric visualizations. From the **DATA SOURCES** dropdown menu, choose the remote metric visualization to add it to the group of visualizations already shown on the dashboard. An example dashboard is shown in the following image. -You can create visualizations based on Prometheus metrics and other metrics collected by your OpenSearch cluster. +Metrics dashboard -To create a visualization, do the following: +To learn about multi-cluster support for data sources, see [Enable OpenSearch Dashboards to support multiple OpenSearch clusters](https://github.com/opensearch-project/OpenSearch-Dashboards/issues/1388). -1. In **Observability** > **Metrics analytics** > **Available Metrics**, select the metrics you would like to include in your visualization. -1. These visualizations can now be saved. -1. From the **Metrics analytics** window, select **Save**. -1. When prompted for a **Custom operational dashboards/application**, choose one of the available options. -1. Optionally, you can edit the predefined name values under the **Metric Name** fields to suit your needs. -1. Select **Save**. +## Creating visualizations based on custom metrics -The following image shows an example of the visualizations that are displayed in the **Observability** > **Metrics analytics** window. +You can create visualizations using the metric data collected by your OpenSearch cluster, including Prometheus metrics and custom metrics. -![Metrics UI example 2]({{site.url}}{{site.baseurl}}/images/metrics/metrics2.png) +To create these visualizations, follow these steps: -## Defining PPL queries for use with Prometheus +1. From the OpenSearch Dashboards main menu, navigate to **Observability** > **Metrics** > **Available Metrics**. +2. Choose the metrics to add to your visualization and then select **Save**. +3. When prompted for a **Custom operational dashboards/application**, choose one of the listed options. You can edit the predefined name values in the **Metric Name** field. +4. Select **Save** to save your visualization. An example visualization is shown in the following image. -You can define [Piped Processing Language]({{site.url}}{{site.baseurl}}/search-plugins/sql/ppl/index) (PPL) queries against metrics collected by Prometheus. The following example shows a metric-selecting query with specific dimensions: +Metrics analytics dashboard with visualizations + +## Defining PPL queries for Prometheus metrics + +You can define [Piped Processing Language (PPL)]({{site.url}}{{site.baseurl}}/search-plugins/sql/ppl/index/) queries to interact with metrics collected by Prometheus. The following is an example PPL query for a Prometheus metric: ``` source = my_prometheus.prometheus_http_requests_total | stats avg(@value) by span(@timestamp,15s), handler, code ``` +{% include copy-curl.html %} + +### Creating a custom visualization based on the PPL query -Additionally, you can create a custom visualization by performing the following steps: +To create a custom visualization based on the PPL query, follow these steps: -1. From the **Events Analytics** window, enter your PPL query and select **Refresh**. The **Explorer page** is now displayed. -1. From the **Explorer page**, select **Save**. -1. When prompted for a **Custom operational dashboards/application**, choose one of the available options. -1. Optionally, you can edit the predefined name values under the **Metric Name** fields to suit your needs. -1. Optionally, you can choose to save the visualization as a metric. -1. Select **Save**. +1. From the **Logs** page, select > **Event Explorer**. +2. On the **Explorer** page, enter your PPL query and select **Run**. Then select **Save**. +3. When prompted to choose a **Custom Operational Dashboards/Application**, select one of the listed options. Optionally, you can edit the predefined name values in the **Metric Name** fields and can choose to save the visualization as a metric. +5. Select **Save** to save your custom visualization. -Note: Only queries that include a time-series visualization and stats/span can be saved as a metric, as shown in the following image. +Only queries that include a time-series visualization and statistics or span information can be saved as a metric, as shown in the following image. -![Metrics UI example 3]({{site.url}}{{site.baseurl}}/images/metrics/metrics3.png) +Saving queries as metrics diff --git a/_observing-your-data/query-insights/top-n-queries.md b/_observing-your-data/query-insights/top-n-queries.md index 44469fa64b..e6dadf33c5 100644 --- a/_observing-your-data/query-insights/top-n-queries.md +++ b/_observing-your-data/query-insights/top-n-queries.md @@ -9,23 +9,28 @@ nav_order: 65 Monitoring the top N queries in query insights features can help you gain real-time insights into the top queries with high latency within a certain time frame (for example, the last hour). -## Getting started +## Configuring top N query monitoring -To enable monitoring of the top N queries, configure the following [dynamic settings]({{site.url}}{{site.baseurl}}/install-and-configure/configuring-opensearch/index/#dynamic-settings): +You can configure top N query monitoring by the following metric types: -- `search.insights.top_queries.latency.enabled`: Set to `true` to [enable monitoring of the top N queries](#enabling-the-top-n-queries-feature). -- `search.insights.top_queries.latency.window_size`: [Configure the window size](#configuring-window-size). -- `search.insights.top_queries.latency.top_n_size`: [Specify the value of n](#configuring-the-value-of-n). +- `latency` +- `cpu` +- `memory` -It's important to exercise caution when enabling this feature because it can consume system resources. -{: .important} +Each metric has a set of corresponding settings: + +- `search.insights.top_queries..enabled`: Set to `true` to [enable top N query monitoring](#enabling-top-n-query-monitoring) by the metric. +- `search.insights.top_queries..window_size`: [Configure the window size of the top N queries](#configuring-the-window-size) by the metric. +- `search.insights.top_queries..top_n_size`: [Specify the value of N for the top N queries by the metric](#configuring-the-value-of-n). +For example, to enable top N query monitoring by CPU usage, set `search.insights.top_queries.cpu.enabled` to `true`. For more information about ways to specify dynamic settings, see [Dynamic settings]({{site.url}}{{site.baseurl}}/install-and-configure/configuring-opensearch/index/#dynamic-settings). -For detailed information about enabling and configuring this feature, see the following sections. +It's important to exercise caution when enabling this feature because it can consume system resources. +{: .important} -## Enabling the top N queries feature +## Enabling top N query monitoring -After installing the `query-insights` plugin, you can enable the top N queries feature (which is disabled by default) by using the following dynamic setting. This setting enables the corresponding collectors and aggregators in the running cluster: +When you install the `query-insights` plugin, top N query monitoring is disabled by default. To enable top N query monitoring, update the dynamic settings for the desired metric types. These settings enable the corresponding collectors and aggregators in the running cluster. For example, to enable top N query monitoring by latency, update the `search.insights.top_queries.latency.enabled` setting: ```json PUT _cluster/settings @@ -37,9 +42,9 @@ PUT _cluster/settings ``` {% include copy-curl.html %} -## Configuring window size +## Configuring the window size -You can configure the window size for the top N queries by latency with `search.insights.top_queries.latency.window_size`. For example, a cluster with the following configuration will collect top N queries in a 60-minute window: +To configure the monitoring window size, update the `window_size` setting for the desired metric type. For example, to collect the top N queries by latency in a 60-minute window, update the `search.insights.top_queries.latency.window_size` setting: ```json PUT _cluster/settings @@ -53,9 +58,9 @@ PUT _cluster/settings ## Configuring the value of N -You can configure the value of N in the `search.insights.top_queries.latency.top_n_size` parameter. For example, a cluster with the following configuration will collect the top 10 queries in the specified window size: +To configure the value of N, update the `top_n_size` setting for the desired metric type. For example, to collect the top 10 queries by latency, update the `insights.top_queries.latency.top_n_size` setting: -``` +```json PUT _cluster/settings { "persistent" : { @@ -67,16 +72,63 @@ PUT _cluster/settings ## Monitoring the top N queries -You can use the Insights API endpoint to obtain top N queries by latency: +You can use the Insights API endpoint to obtain the top N queries for all metric types: ```json GET /_insights/top_queries ``` {% include copy-curl.html %} -Specify a metric type to filter the response by metric type (latency is the only supported type as of 2.12): +Specify a metric type to filter the response: ```json GET /_insights/top_queries?type=latency ``` -{% include copy-curl.html %} \ No newline at end of file +{% include copy-curl.html %} + +```json +GET /_insights/top_queries?type=cpu +``` +{% include copy-curl.html %} + +```json +GET /_insights/top_queries?type=memory +``` +{% include copy-curl.html %} + +## Exporting top N query data + +You can configure your desired exporter to export top N query data to different sinks, allowing for better monitoring and analysis of your OpenSearch queries. Currently, the following exporters are supported: +- [Debug exporter](#configuring-a-debug-exporter) +- [Local index exporter](#configuring-a-local-index-exporter) + +### Configuring a debug exporter + +To configure a debug exporter, update the exporter setting for the desired metric type. For example, to export the top N queries by latency using the debug exporter, send the following request: + +```json +PUT _cluster/settings +{ + "persistent" : { + "search.insights.top_queries.latency.exporter.type" : "debug" + } +} +``` +{% include copy-curl.html %} + +### Configuring a local index exporter + +A local index exporter allows you to export the top N queries to local OpenSearch indexes. The default index pattern for top N query indexes is `top_queries-YYYY.MM.dd`. All top queries from the same day are saved to the same index, and a new index is created each day. You can change the default index pattern to use other date formats. For more information about supported formats, see [DateTimeFormat](https://www.joda.org/joda-time/apidocs/org/joda/time/format/DateTimeFormat.html). + +To configure the local index exporter for the top N queries by latency, send the following request: + +```json +PUT _cluster/settings +{ + "persistent" : { + "search.insights.top_queries.latency.exporter.type" : "local_index", + "search.insights.top_queries.latency.exporter.config.index" : "YYYY.MM.dd" + } +} +``` +{% include copy-curl.html %} diff --git a/_observing-your-data/trace/distributed-tracing.md b/_observing-your-data/trace/distributed-tracing.md index 09fb0f0d39..fb38933711 100644 --- a/_observing-your-data/trace/distributed-tracing.md +++ b/_observing-your-data/trace/distributed-tracing.md @@ -124,7 +124,16 @@ testClusters { ### Enable distributed tracing -Once you've enabled the feature flag, you can enable the tracer (which is disabled by default) by using the following dynamic setting that enables tracing in the running cluster: +Once you've enabled the feature flag, do the following: + +1. Enable the tracing framework feature by adding the following setting in the `opensearch.yaml` file: + +```bash +telemetry.feature.tracer.enabled=true +``` +{% include copy.html %} + +2. Enable the tracer in the running cluster by adding the following dynamic setting: ```bash telemetry.tracer.enabled=true @@ -145,7 +154,7 @@ Currently, the distributed tracing feature generates traces and spans for HTTP r - `telemetry.otel.tracer.exporter.batch_size`: Configures the maximum batch size for each export to reduce input/output. This value should always be less than the `max_queue_size`. Default is `512`. 2. **Exporters:** Exporters are responsible for persisting the data. OpenTelemetry provides several out-of-the-box exporters, and OpenSearch supports the following: - `LoggingSpanExporter`: Exports spans to a log file, generating a separate file in the logs directory `_otel_traces.log`. Default is `telemetry.otel.tracer.span.exporter.class=io.opentelemetry.exporter.logging.LoggingSpanExporter`. - - `OtlpGrpcSpanExporter`: Exports spans through gRPC. To use this exporter, you need to install the `otel-collector` on the node. By default, it writes to the http://localhost:4317/ endpoint. To use this exporter, set the following static setting: `telemetry.otel.tracer.span.exporter.class=org.opensearch.telemetry.tracing.exporter.OtlpGrpcSpanExporterProvider`. + - `OtlpGrpcSpanExporter`: Exports spans through gRPC. To use this exporter, you need to install the `otel-collector` on the node. By default, it writes to the http://localhost:4317/ endpoint. To use this exporter, set the following static setting: `telemetry.otel.tracer.span.exporter.class=io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter`. - `LoggingSpanExporter`: Exports spans to a log file, generating a separate file in the logs directory `_otel_traces.log`. Default is `telemetry.otel.tracer.span.exporter.class=io.opentelemetry.exporter.logging.LoggingSpanExporter`. ### Sampling diff --git a/_observing-your-data/trace/ta-dashboards.md b/_observing-your-data/trace/ta-dashboards.md index 3186093bcc..595dce6ca2 100644 --- a/_observing-your-data/trace/ta-dashboards.md +++ b/_observing-your-data/trace/ta-dashboards.md @@ -1,6 +1,6 @@ --- layout: default -title: OpenSearch Dashboards plugin +title: Trace Analytics plugin for OpenSearch Dashboards parent: Trace Analytics nav_order: 50 redirect_from: @@ -8,18 +8,137 @@ redirect_from: - /monitoring-plugins/trace/ta-dashboards/ --- -# Trace Analytics OpenSearch Dashboards plugin +# Trace Analytics plugin for OpenSearch Dashboards -The Trace Analytics plugin for OpenSearch Dashboards provides at-a-glance visibility into your application performance, along with the ability to drill down on individual traces. For installation instructions, see [Standalone OpenSearch Dashboards plugin install]({{site.url}}{{site.baseurl}}/install-and-configure/install-dashboards/plugins/). +The Trace Analytics plugin offers at-a-glance visibility into application performance based on [OpenTelemetry (OTel)](https://opentelemetry.io/) protocol data that standardizes instrumentation for collecting telemetry data from cloud-native software. -The **Dashboard** view groups traces together by HTTP method and path so that you can see the average latency, error rate, and trends associated with a particular operation. For a more focused view, try filtering by trace group name. +## Installing the plugin -![Dashboard view]({{site.url}}{{site.baseurl}}/images/ta-dashboard.png) +See [Standalone OpenSearch Dashboards plugin install]({{site.url}}{{site.baseurl}}/install-and-configure/install-dashboards/plugins/) for instructions on how to install the Trace Analytics plugin. -To drill down on the traces that make up a trace group, choose the number of traces in the column on the right. Then choose an individual trace for a detailed summary. +## Setting up the OpenTelemetry Demo -![Detailed trace view]({{site.url}}{{site.baseurl}}/images/ta-trace.png) +The [OpenTelemetry Demo with OpenSearch](https://github.com/opensearch-project/opentelemetry-demo) simulates a distributed application generating real-time telemetry data, providing you with a practical environment in which to explore features available with the Trace Analytics plugin before implementing it in your environment. -The **Services** view lists all services in the application, plus an interactive map that shows how the various services connect to each other. In contrast to the dashboard, which helps identify problems by operation, the service map helps identify problems by service. Try sorting by error rate or latency to get a sense of potential problem areas of your application. -![Service view]({{site.url}}{{site.baseurl}}/images/ta-services.png) +**Step 1: Set up the OpenTelemetry Demo** + + - Clone the [OpenTelemetry Demo with OpenSearch](https://github.com/opensearch-project/opentelemetry-demo) repository: `git clone https://github.com/opensearch-project/opentelemetry-demo`. + - Follow the [Getting Started](https://github.com/opensearch-project/opentelemetry-demo/blob/main/tutorial/GettingStarted.md) instructions to deploy the demo application using Docker, which runs multiple microservices generating telemetry data. + +**Step 2: Ingest telemetry data** + + - Configure the OTel collectors to send telemetry data (traces, metrics, logs) to your OpenSearch cluster, using the [preexisting setup](https://github.com/opensearch-project/opentelemetry-demo/tree/main/src/otelcollector). + - Confirm that [Data Prepper](https://github.com/opensearch-project/opentelemetry-demo/tree/main/src/dataprepper) is set up to process the incoming data, handle trace analytics and service map pipelines, submit data to required indexes, and perform preaggregated calculations. + +**Step 3: Explore Trace Analytics in OpenSearch Dashboards** + +The **Trace Analytics** application includes two options: **Services** and **Traces**: + + - **Services** lists all services in the application, plus an interactive map that shows how the various services connect to each other. In contrast to the dashboard (which helps identify problems by operation), the **Service map** helps you identify problems by service based on error rates and latency. To access this option, go to **Trace Analytics** > **Services**. + - **Traces** groups traces together by HTTP method and path so that you can see the average latency, error rate, and trends associated with a particular operation. For a more focused view, try filtering by trace group name. To access this option, go to **Trace Analytics** > **Traces**. From the **Trace Groups** panel, you can review the traces that comprise a trace group. From the **Traces** panel you can analyze individual traces for a detailed summary. + + **Step 4: Perform correlation analysis** + - Select **Services correlation** to display connections between various telemetry signals. This allows you to navigate from the logical service level to the associated metrics and logs for that specific service. + +--- + +## Schema dependencies and assumptions + +The plugin requires you to use [Data Prepper]({{site.url}}{{site.baseurl}}/data-prepper/) to process and visualize OTel data and relies on the following Data Prepper pipelines for OTel correlations and service map calculations: + +- [Trace analytics pipeline]({{site.url}}{{site.baseurl}}/data-prepper/common-use-cases/trace-analytics/) +- [Service map pipeline]({{site.url}}{{site.baseurl}}/data-prepper/pipelines/configuration/processors/service-map-stateful/) + +### Standardized telemetry data + +The plugin requires telemetry data to follow the OTel schema conventions, including the structure and naming of spans, traces, and metrics as specified by OTel, and to be implemented using the [Simple Schema for Observability]({{site.url}}{{site.baseurl}}/observing-your-data/ss4o/). + +### Service names and dependency map + +For accurate service mapping and correlation analysis, adhere to the following guidelines: + +- Service names must be unique and used consistently across application components. +- The `serviceName` field must be populated using the Data Prepper pipeline. +- Services must be ingested with predefined upstream and downstream dependencies to construct accurate service maps and understand service relationships. + +### Trace and span IDs + +Traces and spans must have consistently generated and maintained unique identifiers across distributed systems to enable end-to-end tracing and accurate performance insights. + +### RED metrics adherence + +The plugin expects metric data to include rate, error, and duration (RED) indicators for each service, either preaggregated using the Data Prepper pipeline or calculated dynamically based on spans. This allows you to effectively compute and display key performance indicators. + +### Correlation fields + +Certain fields, such as `serviceName`, must be present to perform correlation analysis. These fields enable the plugin to link related telemetry data and provide a holistic view of service interactions and dependencies. + +### Correlation indexes + +Navigating from the service dialog to its corresponding traces or logs requires the existence of correlating fields and that the target indexes (for example, logs) follow the specified naming conventions, as described at [Simple Schema for Observability](https://opensearch.org/docs/latest/observing-your-data/ss4o/). + +--- + +## Trace analytics with OTel protocol analytics +Introduced 2.15 +{: .label .label-purple } + +Trace analytics with OTel protocol analytics provide comprehensive insights into distributed systems. You can visualize and analyze the following assets: + +- [Service](https://opentelemetry.io/docs/specs/semconv/resource/#service): The components of a distributed application. These components are significant logical terms used to measure and monitor the application's building blocks in order to validate the system's health. +- [Traces](https://opentelemetry.io/docs/concepts/signals/traces/): A visual representation of a request's path across services into requests' journeys across services, offering insights into latency and performance issues. +- [RED metrics](https://opentelemetry.io/docs/specs/otel/metrics/api/): Metrics for service health and performance, measured as requests per second (rate), failed requests (errors), and request processing time (duration). + +### Trace analytics visualizations + +**Services** visualizations, such as a table or map, help you logically analyze service behavior and accuracy. The following visualizations can help you identify anomalies and errors: + +- **Services table** + - A RED indicator, along with connected upstream and downstream services and other actions, is indicated in each table column. An example **Services** table is shown in the following image. + + ![Services table]({{site.url}}{{site.baseurl}}/images/trace-analytics/services-table.png) + + - General-purpose filter selection is used for field or filter composition. The following image shows this filter. + + ![Services filter selection]({{site.url}}{{site.baseurl}}/images/trace-analytics/services-filter-selection.png) + + - The **Services** throughput tooltip provides an at-a-glance overview of a service's incoming request trend for the past 24 hours. The following image shows an example tooltip. + + ![Services throughput tooltip ]({{site.url}}{{site.baseurl}}/images/trace-analytics/service-throughput-tooltip.png) + + - The **Services** correlation dialog window provides an at-a-glance overview of a service's details, including its 24-hour throughput trend. You can use these details to analyze correlated logs or traces by filtering based on the `serviceName` field. The following image shows this window. + + ![Services correlation dialog window]({{site.url}}{{site.baseurl}}/images/trace-analytics/single-service-correlation-dialog.png) + + - The **Services** RED metrics dialog window provides an at-a-glance overview of a service's RED metrics indicators, including 24-hour error, duration, and throughput rate. The following image shows this window. + + ![Services RED metrics for duration]({{site.url}}{{site.baseurl}}/images/trace-analytics/single-service-RED-metrics.png) + + - The **Span details** dialog window provides the details of a trace. You can use this information to further analyze a trace's elements, such as attributes and associated logs. The following image shows this window. + + ![Services Span details dialog window]({{site.url}}{{site.baseurl}}/images/trace-analytics/span-details-fly-out.png) + +- **Service map** + - The **Service map** displays nodes, each representing a service. The node color indicates the RED indicator severity for that service and its dependencies. The following image shows a map. + + ![Services map tooltip]({{site.url}}{{site.baseurl}}/images/trace-analytics/service-details-tooltip.png) + + - You can select a node to open a detailed dialog window for its associated service. This interactive map visualizes service interconnections, helping identify problems by service, unlike dashboards that identify issues by operation. You can sort by error rate or latency to pinpoint potential problem areas. + + - In the **Service map** dialog window, nodes represent connected downstream services dependent on the selected service. The node color indicates the RED indicator severity for that service and its downstream dependencies. The following image shows this dialog window. + + ![Service map dialog window]({{site.url}}{{site.baseurl}}/images/trace-analytics/single-service-fly-out.png) + +- **Trace groups** + - Traces are grouped by their HTTP API name, allowing clustering based on their business functional unit. Traces are grouped by HTTP method and path, displaying the average latency, error rate, and trends associated with a particular operation. You can filter by trace group name. The following image shows the **Trace Groups** window. + + ![Trace Groups window]({{site.url}}{{site.baseurl}}/images/trace-analytics/trace-group-RED-metrics.png) + + - In the **Trace Groups** window, you can filter by group name and other filters. You can also analyze associated traces. To drill down on the traces that comprise a group, select the number of traces in the right-hand column and then choose an individual trace to see a detailed summary. + + ![Trace group dialog window]({{site.url}}{{site.baseurl}}/images/ta-dashboard.png) + + - The **Trace details** window displays a breakdown of a single trace, including its corresponding spans, associated service names, and a waterfall chart of the spans' time and duration interactions. The following image shows this view. + + ![Trace details window]({{site.url}}{{site.baseurl}}/images/ta-trace.png) diff --git a/_plugins/link-checker.rb b/_plugins/link-checker.rb index 9eb9c48bc9..dc6236096d 100644 --- a/_plugins/link-checker.rb +++ b/_plugins/link-checker.rb @@ -64,7 +64,9 @@ class CheckTypes 'crates.io', # 404s on bots 'www.cloudflare.com', # 403s on bots 'platform.openai.com', # 403s on bots + 'openai.com', # 403s on bots 'mvnrepository.com', # 403s on bots + 'www.intel.com', # 403s on bots 'example.issue.link' # a fake example link from the template ] @@ -259,7 +261,7 @@ def self.check_external(url, location) # Check if an internal link is accessible def self.check_internal(url, location) - Jekyll.logger.info "LinkChecker: [Info] Checking #{url}".cyan + Jekyll.logger.info "LinkChecker: [Info] Checking #{url} (#{location})".cyan return true if @ignored_paths =~ url path, hash = url.split('#') diff --git a/_query-dsl/compound/index.md b/_query-dsl/compound/index.md index d1ad1e26ef..d1051bafa3 100644 --- a/_query-dsl/compound/index.md +++ b/_query-dsl/compound/index.md @@ -5,8 +5,10 @@ has_children: true has_toc: false nav_order: 40 redirect_from: + - /opensearch/query-dsl/compound/index/ - /query-dsl/compound/index/ - /query-dsl/query-dsl/compound/ + - /query-dsl/compound/ --- # Compound queries diff --git a/_query-dsl/geo-and-xy/index.md b/_query-dsl/geo-and-xy/index.md index a1d76f0477..44e2df9b49 100644 --- a/_query-dsl/geo-and-xy/index.md +++ b/_query-dsl/geo-and-xy/index.md @@ -7,6 +7,7 @@ redirect_from: - /opensearch/query-dsl/geo-and-xy/index/ - /query-dsl/query-dsl/geo-and-xy/ - /query-dsl/query-dsl/geo-and-xy/index/ + - /query-dsl/geo-and-xy/ --- # Geographic and xy queries diff --git a/_query-dsl/query-filter-context.md b/_query-dsl/query-filter-context.md index 6985822e03..64d45b8d7b 100644 --- a/_query-dsl/query-filter-context.md +++ b/_query-dsl/query-filter-context.md @@ -3,7 +3,8 @@ layout: default title: Query and filter context nav_order: 5 redirect_from: -- /query-dsl/query-dsl/query-filter-context/ + - /opensearch/query-dsl/query-filter-context/ + - /query-dsl/query-dsl/query-filter-context/ --- # Query and filter context diff --git a/_query-dsl/term-vs-full-text.md b/_query-dsl/term-vs-full-text.md index e5019c4eb2..61d57c67f8 100644 --- a/_query-dsl/term-vs-full-text.md +++ b/_query-dsl/term-vs-full-text.md @@ -3,7 +3,8 @@ layout: default title: Term-level and full-text queries compared nav_order: 10 redirect_from: -- /query-dsl/query-dsl/term-vs-full-text + - /query-dsl/query-dsl/term-vs-full-text/ + - /opensearch/query-dsl/term-vs-full-text/ --- # Term-level and full-text queries compared diff --git a/_query-dsl/term/index.md b/_query-dsl/term/index.md index 594ece3fb5..4a789b0b72 100644 --- a/_query-dsl/term/index.md +++ b/_query-dsl/term/index.md @@ -4,6 +4,9 @@ title: Term-level queries has_children: true has_toc: false nav_order: 20 +redirect_from: + - /opensearch/query-dsl/term/ + - /query-dsl/term/ --- # Term-level queries diff --git a/_search-plugins/caching/index.md b/_search-plugins/caching/index.md index d155caf86b..000d0b61c1 100644 --- a/_search-plugins/caching/index.md +++ b/_search-plugins/caching/index.md @@ -16,7 +16,7 @@ Understanding how your data uses the cache can help improve your cluster's perfo OpenSearch supports the following on-heap cache types: -- **Request cache**: Caches the local results on each shard. This allows frequently used and potentially resource-heavy search requests to return results almost instantaneously. +- [**Index request cache**]({{site.url}}{{site.baseurl}}/search-plugins/caching/request-cache/): Caches the local results on each shard. This allows frequently used and potentially resource-heavy search requests to return results almost instantaneously. - **Query cache**: Caches common data from similar queries at the shard level. The query cache is more granular than the request cache and can cache data to be reused in different queries. - **Field data cache**: Caches field data and global ordinals, which are both used to support aggregations on certain field types. diff --git a/_search-plugins/caching/request-cache.md b/_search-plugins/caching/request-cache.md new file mode 100644 index 0000000000..124152300b --- /dev/null +++ b/_search-plugins/caching/request-cache.md @@ -0,0 +1,158 @@ +--- +layout: default +title: Index request cache +parent: Caching +grand_parent: Improving search performance +nav_order: 5 +--- + +# Index request cache + +The OpenSearch index request cache is a specialized caching mechanism designed to enhance search performance by storing the results of frequently executed search queries at the shard level. This reduces cluster load and improves response times for repeated searches. This cache is enabled by default and is particularly useful for read-heavy workloads where certain queries are executed frequently. + +The cache is automatically invalidated at the configured refresh interval. The invalidation includes document updates (including document deletions) and changes to index settings. This ensures that stale results are never returned from the cache. When the cache size exceeds its configured limit, the least recently used entries are evicted to make room for new entries. + +Search requests with `size=0` are cached in the request cache by default. Search requests with non-deterministic characteristics (such as `Math.random()`) or relative times (such as `now` or `new Date()`) are ineligible for caching. +{: .note} + +## Configuring request caching + +You can configure the index request cache by setting the parameters in the `opensearch.yml` configuration file or using the REST API. For more information, see [Index settings]({{site.url}}{{site.baseurl}}/install-and-configure/configuring-opensearch/index-settings/). + +### Settings + +The following table lists the index request cache settings. For more information about dynamic settings, see [Index settings]({{site.url}}{{site.baseurl}}/install-and-configure/configuring-opensearch/index-settings/). + +Setting | Data type | Default | Level | Static/Dynamic | Description +:--- |:-----------|:--------| :--- | :--- | :--- +`indices.cache.cleanup_interval` | Time unit | `1m` (1 minute) | Cluster | Static | Schedules a recurring background task that cleans up expired entries from the cache at the specified interval. +`indices.requests.cache.size` | Percentage | `1%` | Cluster | Static | The cache size as a percentage of the heap size (for example, to use 1% of the heap, specify `1%`). +`index.requests.cache.enable` | Boolean | `true` | Index | Dynamic | Enables or disables the request cache. + +### Example + +To disable the request cache for an index, send the following request: + +```json +PUT /my_index/_settings +{ + "index.requests.cache.enable": false +} +``` +{% include copy-curl.html %} + +## Caching specific requests + +In addition to providing index-level or cluster-level settings for the request cache, you can also cache specific search requests selectively by setting the `request_cache` query parameter to `true`: + +```json +GET /students/_search?request_cache=true +{ + "query": { + "match": { + "name": "doe john" + } + } +} +``` +{% include copy-curl.html %} + +## Monitoring the request cache + +Monitoring cache usage and performance is crucial to maintaining an efficient caching strategy. OpenSearch provides several APIs to help monitor the cache. + +### Retrieving cache statistics for all nodes + +The [Nodes Stats API]({{site.url}}{{site.baseurl}}/api-reference/nodes-apis/nodes-stats/) returns cache statistics for all nodes in a cluster: + +```json +GET /_nodes/stats/indices/request_cache +``` +{% include copy-curl.html %} + +The response contains the request cache statistics: + +```json +{ + "nodes": { + "T7aqO6zaQX-lt8XBWBYLsA": { + "indices": { + "request_cache": { + "memory_size_in_bytes": 10240, + "evictions": 0, + "hit_count": 50, + "miss_count": 10 + } + } + } + } +} +``` +{% include copy-curl.html %} + +### Retrieving cache statistics for a specific index + +The [Index Stats API]({{site.url}}{{site.baseurl}}/api-reference/index-apis/stats/) returns cache statistics for a specific index: + +```json +GET /my_index/_stats/request_cache +``` +{% include copy-curl.html %} + +The response contains the request cache statistics: + +```json +{ + "_shards": { + "total": 5, + "successful": 5, + "failed": 0 + }, + "_all": { + "primaries": { + "request_cache": { + "memory_size_in_bytes": 2048, + "evictions": 1, + "hit_count": 30, + "miss_count": 5 + } + }, + "total": { + "request_cache": { + "memory_size_in_bytes": 4096, + "evictions": 2, + "hit_count": 60, + "miss_count": 10 + } + } + }, + "indices": { + "my_index": { + "primaries": { + "request_cache": { + "memory_size_in_bytes": 2048, + "evictions": 1, + "hit_count": 30, + "miss_count": 5 + } + }, + "total":{ + "request_cache": { + "memory_size_in_bytes": 4096, + "evictions": 2, + "hit_count": 60, + "miss_count": 10 + } + } + } + } +} +``` + +## Best practices + +When using the index request cache, consider the following best practices: + +- **Appropriate cache size**: Configure the cache size based on your query patterns. A larger cache can store more results but may consume significant resources. +- **Query optimization**: Ensure that frequently executed queries are optimized so that they can benefit from caching. +- **Monitoring**: Regularly monitor cache hit and cache miss rates to understand cache efficiency and make necessary adjustments. \ No newline at end of file diff --git a/_search-plugins/caching/tiered-cache.md b/_search-plugins/caching/tiered-cache.md index 10cdeacab7..22b1138be8 100644 --- a/_search-plugins/caching/tiered-cache.md +++ b/_search-plugins/caching/tiered-cache.md @@ -44,7 +44,7 @@ In OpenSearch 2.14, a request cache can be used in a tiered cache. To begin, con To use the OpenSearch-provided tiered spillover cache implementation, set the cache store name to `tiered_spillover`, as shown in the following example: ```yaml -indices.request.cache.store.name: tiered_spillover: true +indices.request.cache.store.name: tiered_spillover ``` {% include copy.html %} @@ -90,3 +90,21 @@ Setting | Data type | Default | Description :--- | :--- | :--- | :--- `indices.request.cache.tiered_spillover.disk.store.policies.took_time.threshold` | Time unit | `10ms` | A policy used to determine whether to cache a query into a disk cache based on its took time. This is a dynamic setting. Optional. `indices.request.cache.tiered_spillover.disk.store.enabled` | Boolean | `True` | Enables or disables the disk cache dynamically within a tiered spillover cache. Note: After disabling a disk cache, entries are not removed automatically and requires the cache to be manually cleared. Optional. + +### Delete stale entries settings + +The following table lists the settings related to the deletion of stale entries from the cache. + +Setting | Data type | Default | Description +:--- | :--- |:--------| :--- +`indices.requests.cache.cleanup.staleness_threshold` | String | `0%` | Defines the percentage of stale keys in the cache post. After identification, all stale cache entries are deleted. Optional. +`indices.requests.cache.cleanup.interval` | Time unit | `1m` | Defines the frequency at which the request cache's stale entries are deleted. Optional. + +## Getting statistics for the `tiered_spillover` store + +To assess the impact of using the tiered spillover cache, use the [Node Stats API]({{site.url}}{{site.baseurl}}/api-reference/nodes-apis/nodes-stats/#caches), as shown in the following example: + +```json +GET /_nodes/stats/caches/request_cache?level=tier +``` + diff --git a/_search-plugins/concurrent-segment-search.md b/_search-plugins/concurrent-segment-search.md index 4bc0e5ca76..9c0e2da7c6 100644 --- a/_search-plugins/concurrent-segment-search.md +++ b/_search-plugins/concurrent-segment-search.md @@ -82,6 +82,14 @@ The `search.concurrent.max_slice_count` setting can take the following valid val - `0`: Use the default Lucene mechanism. - Positive integer: Use the max target slice count mechanism. Usually, a value between 2 and 8 should be sufficient. +## General guidelines +Concurrent segment search helps to improve the performance of search requests at the cost of consuming more resources, such as CPU or JVM heap. It is important to test your workload in order to understand whether the cluster is sized correctly for concurrent segment search. We recommend adhering to the following concurrent segment search guidelines: + +* Start with a slice count of 2 and measure the performance of your workload. If resource utilization exceeds the recommended values, then consider scaling your cluster. Based on our testing, we have observed that if your workload is already consuming more than 50% of your CPU resources, then you need to scale your cluster for concurrent segment search. +* If your slice count is 2 and you still have available resources in the cluster, then you can increase the slice count to a higher number, such as 4 or 6, while monitoring search latency and resource utilization in the cluster. +* When many clients send search requests in parallel, a lower slice count usually works better. This is reflected in CPU utilization because a higher number of clients leads to more queries per second, which translates to higher resource usage. + + ## Limitations The following aggregations do not support the concurrent search model. If a search request contains one of these aggregations, the request will be executed using the non-concurrent path even if concurrent segment search is enabled at the cluster level or index level. diff --git a/_search-plugins/cross-cluster-search.md b/_search-plugins/cross-cluster-search.md index c25f3d70d9..947097e8b3 100644 --- a/_search-plugins/cross-cluster-search.md +++ b/_search-plugins/cross-cluster-search.md @@ -285,7 +285,7 @@ curl -XGET -k -u 'admin:' 'https://opensearch-domain-1:92 ## Sample Kubernetes/Helm setup If you are using Kubernetes clusters to deploy OpenSearch, you need to configure the remote cluster using either the `LoadBalancer` or `Ingress`. The Kubernetes services created using the following [Helm]({{site.url}}{{site.baseurl}}/install-and-configure/install-opensearch/helm/) example are of the `ClusterIP` type and are only accessible from within the cluster; therefore, you must use an externally accessible endpoint: -```json +```bash curl -k -XPUT -H 'Content-Type: application/json' -u 'admin:' 'https://opensearch-domain-1:9200/_cluster/settings' -d ' { "persistent": { @@ -297,3 +297,68 @@ curl -k -XPUT -H 'Content-Type: application/json' -u 'admin::9300; + } + upstream opensearch-http { + server :9200; + } + server { + listen 8300; + ssl_certificate /.../{{site.opensearch_version}}/config/esnode.pem; + ssl_certificate_key /.../{{site.opensearch_version}}/config/esnode-key.pem; + ssl_trusted_certificate /.../{{site.opensearch_version}}/config/root-ca.pem; + proxy_pass opensearch-transport; + ssl_preread on; + } + server { + listen 443; + listen [::]:443; + ssl_certificate /.../{{site.opensearch_version}}/config/esnode.pem; + ssl_certificate_key /.../{{site.opensearch_version}}/config/esnode-key.pem; + ssl_trusted_certificate /.../{{site.opensearch_version}}/config/root-ca.pem; + proxy_pass opensearch-http; + ssl_preread on; + } +} +``` + +The listening ports for HTTP and transport communication are set to `443` and `8300`, respectively. + +### OpenSearch configuration + +The remote cluster can be configured to point to the `proxy` by using the following command: + +```bash +curl -k -XPUT -H 'Content-Type: application/json' -u 'admin:' 'https://opensearch:9200/_cluster/settings' -d ' +{ + "persistent": { + "cluster.remote": { + "opensearch-remote-cluster": { + "mode": "proxy", + "proxy_address": ":8300" + } + } + } +}' +``` + +Note the previously configured port `8300` in the [Proxy configuration]({{site.url}}{{site.baseurl}}/search-plugins/cross-cluster-search/#proxy-configuration) section. diff --git a/_search-plugins/knn/approximate-knn.md b/_search-plugins/knn/approximate-knn.md index 7d3e119349..c0a9557728 100644 --- a/_search-plugins/knn/approximate-knn.md +++ b/_search-plugins/knn/approximate-knn.md @@ -127,10 +127,26 @@ GET my-knn-index-1/_search } ``` -`k` is the number of neighbors the search of each graph will return. You must also include the `size` option, which -indicates how many results the query actually returns. The plugin returns `k` amount of results for each shard -(and each segment) and `size` amount of results for the entire query. The plugin supports a maximum `k` value of 10,000. -Starting in OpenSearch 2.14, in addition to using the `k` variable, both the `min_score` and `max_distance` variables can be used for [radial search]({{site.url}}{{site.baseurl}}/search-plugins/knn/radial-search-knn/). +### The number of returned results + +In the preceding query, `k` represents the number of neighbors returned by the search of each graph. You must also include the `size` option, indicating the final number of results that you want the query to return. + +For the NMSLIB and Faiss engines, `k` represents the maximum number of documents returned for all segments of a shard. For the Lucene engine, `k` represents the number of documents returned for a shard. The maximum value of `k` is 10,000. + +For any engine, each shard returns `size` results to the coordinator node. Thus, the total number of results that the coordinator node receives is `size * number of shards`. After the coordinator node consolidates the results received from all nodes, the query returns the top `size` results. + +The following table provides examples of the number of results returned by various engines in several scenarios. For these examples, assume that the number of documents contained in the segments and shards is sufficient to return the number of results specified in the table. + +`size` | `k` | Number of primary shards | Number of segments per shard | Number of returned results, Faiss/NMSLIB | Number of returned results, Lucene +:--- | :--- | :--- | :--- | :--- | :--- +10 | 1 | 1 | 4 | 4 | 1 +10 | 10 | 1 | 4 | 10 | 10 +10 | 1 | 2 | 4 | 8 | 2 + +The number of results returned by Faiss/NMSLIB differs from the number of results returned by Lucene only when `k` is smaller than `size`. If `k` and `size` are equal, all engines return the same number of results. + +Starting in OpenSearch 2.14, you can use `k`, `min_score`, or `max_distance` for [radial search]({{site.url}}{{site.baseurl}}/search-plugins/knn/radial-search-knn/). + ### Building a k-NN index from a model For some of the algorithms that we support, the native library index needs to be trained before it can be used. It would be expensive to training every newly created segment, so, instead, we introduce the concept of a *model* that is used to initialize the native library index during segment creation. A *model* is created by calling the [Train API]({{site.url}}{{site.baseurl}}/search-plugins/knn/api#train-a-model), passing in the source of training data as well as the method definition of the model. Once training is complete, the model will be serialized to a k-NN model system index. Then, during indexing, the model is pulled from this index to initialize the segments. @@ -311,4 +327,4 @@ included in the distance function. With cosine similarity, it is not valid to pass a zero vector (`[0, 0, ...]`) as input. This is because the magnitude of such a vector is 0, which raises a `divide by 0` exception in the corresponding formula. Requests containing the zero vector will be rejected and a corresponding exception will be thrown. -{: .note } \ No newline at end of file +{: .note } diff --git a/_search-plugins/knn/knn-vector-quantization.md b/_search-plugins/knn/knn-vector-quantization.md index 96db75b3eb..549437f346 100644 --- a/_search-plugins/knn/knn-vector-quantization.md +++ b/_search-plugins/knn/knn-vector-quantization.md @@ -51,7 +51,7 @@ PUT /test-index "space_type": "l2", "parameters": { "encoder": { - "name": "sq", + "name": "sq" }, "ef_construction": 256, "m": 8 diff --git a/_search-plugins/knn/nested-search-knn.md b/_search-plugins/knn/nested-search-knn.md index 49465edea5..bdc1045387 100644 --- a/_search-plugins/knn/nested-search-knn.md +++ b/_search-plugins/knn/nested-search-knn.md @@ -48,6 +48,10 @@ PUT my-knn-index-1 "m": 16 } } + }, + "color": { + "type": "text", + "index": false } } } @@ -62,9 +66,9 @@ After you create the index, add some data to it: ```json PUT _bulk?refresh=true { "index": { "_index": "my-knn-index-1", "_id": "1" } } -{"nested_field":[{"my_vector":[1,1,1]},{"my_vector":[2,2,2]},{"my_vector":[3,3,3]}]} +{"nested_field":[{"my_vector":[1,1,1], "color": "blue"},{"my_vector":[2,2,2], "color": "yellow"},{"my_vector":[3,3,3], "color": "white"}]} { "index": { "_index": "my-knn-index-1", "_id": "2" } } -{"nested_field":[{"my_vector":[10,10,10]},{"my_vector":[20,20,20]},{"my_vector":[30,30,30]}]} +{"nested_field":[{"my_vector":[10,10,10], "color": "red"},{"my_vector":[20,20,20], "color": "green"},{"my_vector":[30,30,30], "color": "black"}]} ``` {% include copy-curl.html %} @@ -94,7 +98,7 @@ Even though all three vectors nearest to the query vector are in document 1, the ```json { - "took": 23, + "took": 5, "timed_out": false, "_shards": { "total": 1, @@ -107,12 +111,12 @@ Even though all three vectors nearest to the query vector are in document 1, the "value": 2, "relation": "eq" }, - "max_score": 1, + "max_score": 1.0, "hits": [ { "_index": "my-knn-index-1", "_id": "1", - "_score": 1, + "_score": 1.0, "_source": { "nested_field": [ { @@ -120,21 +124,24 @@ Even though all three vectors nearest to the query vector are in document 1, the 1, 1, 1 - ] + ], + "color": "blue" }, { "my_vector": [ 2, 2, 2 - ] + ], + "color": "yellow" }, { "my_vector": [ 3, 3, 3 - ] + ], + "color": "white" } ] } @@ -150,21 +157,24 @@ Even though all three vectors nearest to the query vector are in document 1, the 10, 10, 10 - ] + ], + "color": "red" }, { "my_vector": [ 20, 20, 20 - ] + ], + "color": "green" }, { "my_vector": [ 30, 30, 30 - ] + ], + "color": "black" } ] } @@ -174,6 +184,123 @@ Even though all three vectors nearest to the query vector are in document 1, the } ``` +## Inner hits + +When you retrieve documents based on matches in nested fields, by default, the response does not contain information about which inner objects matched the query. Thus, it is not apparent why the document is a match. To include information about the matching nested fields in the response, you can provide the `inner_hits` object in your query. To return only certain fields of the matching documents within `inner_hits`, specify the document fields in the `fields` array. Generally, you should also exclude `_source` from the results to avoid returning the whole document. The following example returns only the `color` inner field of the `nested_field`: + +```json +GET my-knn-index-1/_search +{ + "_source": false, + "query": { + "nested": { + "path": "nested_field", + "query": { + "knn": { + "nested_field.my_vector": { + "vector": [1,1,1], + "k": 2 + } + } + }, + "inner_hits": { + "_source": false, + "fields":["nested_field.color"] + } + } + } +} +``` +{% include copy-curl.html %} + +The response contains matching documents. For each matching document, the `inner_hits` object contains only the `nested_field.color` fields of the matched documents in the `fields` array: + +```json +{ + "took": 4, + "timed_out": false, + "_shards": { + "total": 1, + "successful": 1, + "skipped": 0, + "failed": 0 + }, + "hits": { + "total": { + "value": 2, + "relation": "eq" + }, + "max_score": 1.0, + "hits": [ + { + "_index": "my-knn-index-1", + "_id": "1", + "_score": 1.0, + "inner_hits": { + "nested_field": { + "hits": { + "total": { + "value": 1, + "relation": "eq" + }, + "max_score": 1.0, + "hits": [ + { + "_index": "my-knn-index-1", + "_id": "1", + "_nested": { + "field": "nested_field", + "offset": 0 + }, + "_score": 1.0, + "fields": { + "nested_field.color": [ + "blue" + ] + } + } + ] + } + } + } + }, + { + "_index": "my-knn-index-1", + "_id": "2", + "_score": 0.0040983604, + "inner_hits": { + "nested_field": { + "hits": { + "total": { + "value": 1, + "relation": "eq" + }, + "max_score": 0.0040983604, + "hits": [ + { + "_index": "my-knn-index-1", + "_id": "2", + "_nested": { + "field": "nested_field", + "offset": 0 + }, + "_score": 0.0040983604, + "fields": { + "nested_field.color": [ + "red" + ] + } + } + ] + } + } + } + } + ] + } +} +``` + ## k-NN search with filtering on nested fields You can apply a filter to a k-NN search with nested fields. A filter can be applied to either a top-level field or a field inside a nested field. diff --git a/_search-plugins/knn/performance-tuning.md b/_search-plugins/knn/performance-tuning.md index d2cf3c7759..24d92bd67d 100644 --- a/_search-plugins/knn/performance-tuning.md +++ b/_search-plugins/knn/performance-tuning.md @@ -18,11 +18,11 @@ This topic also provides recommendations for comparing approximate k-NN to exact ## Indexing performance tuning -Take the following steps to improve indexing performance, especially when you plan to index a large number of vectors at once: +Take any of the following steps to improve indexing performance, especially when you plan to index a large number of vectors at once. -* **Disable the refresh interval** +### Disable the refresh interval - Either disable the refresh interval (default = 1 sec), or set a long duration for the refresh interval to avoid creating multiple small segments: +Either disable the refresh interval (default = 1 sec) or set a long duration for the refresh interval to avoid creating multiple small segments: ```json PUT //_settings @@ -32,23 +32,78 @@ Take the following steps to improve indexing performance, especially when you pl } } ``` - **Note**: Make sure to reenable `refresh_interval` after indexing finishes. -* **Disable replicas (no OpenSearch replica shard)** +Make sure to reenable `refresh_interval` after indexing is complete. - Set replicas to `0` to prevent duplicate construction of native library indexes in both primary and replica shards. When you enable replicas after indexing finishes, the serialized native library indexes are directly copied. If you have no replicas, losing nodes might cause data loss, so it's important that the data lives elsewhere so this initial load can be retried in case of an issue. +### Disable replicas (no OpenSearch replica shard) -* **Increase the number of indexing threads** + Set replicas to `0` to prevent duplicate construction of native library indexes in both primary and replica shards. When you enable replicas after indexing completes, the serialized native library indexes are copied directly. If you have no replicas, losing nodes might cause data loss, so it's important that the data be stored elsewhere so that this initial load can be retried in the event of an issue. - If the hardware you choose has multiple cores, you can allow multiple threads in native library index construction by speeding up the indexing process. Determine the number of threads to allot with the [knn.algo_param.index_thread_qty]({{site.url}}{{site.baseurl}}/search-plugins/knn/settings#cluster-settings) setting. +### Increase the number of indexing threads - Keep an eye on CPU utilization and choose the correct number of threads. Because native library index construction is costly, having multiple threads can cause additional CPU load. +If your hardware has multiple cores, you can allow multiple threads in native library index construction by speeding up the indexing process. Determine the number of threads to allot with the [knn.algo_param.index_thread_qty]({{site.url}}{{site.baseurl}}/search-plugins/knn/settings#cluster-settings) setting. + +Monitor CPU utilization and choose the correct number of threads. Because native library index construction is costly, choosing more threads then you need can cause additional CPU load. + + +### (Expert-level) Disable vector field storage in the source field + +The `_source` field contains the original JSON document body that was passed at index time. This field is not indexed and is not searchable but is stored so that it can be returned when executing fetch requests such as `get` and `search`. When using vector fields within the source, you can remove the vector field to save disk space, as shown in the following example where the `location` vector is excluded: + + ```json + PUT //_mappings + { + "_source": { + "excludes": ["location"] + }, + "properties": { + "location": { + "type": "knn_vector", + "dimension": 2, + "method": { + "name": "hnsw", + "space_type": "l2", + "engine": "faiss" + } + } + } + } + ``` + + +Disabling the `_source` field can cause certain features to become unavailable, such as the `update`, `update_by_query`, and `reindex` APIs and the ability to debug queries or aggregations by using the original document at index time. + +In OpenSearch 2.15 or later, you can further improve indexing speed and reduce disk space by removing the vector field from the `_recovery_source`, as shown in the following example: + + ```json + PUT //_mappings + { + "_source": { + "excludes": ["location"], + "recovery_source_excludes": ["location"] + }, + "properties": { + "location": { + "type": "knn_vector", + "dimension": 2, + "method": { + "name": "hnsw", + "space_type": "l2", + "engine": "faiss" + } + } + } + } + ``` + +This is an expert-level setting. Disabling the `_recovery_source` may lead to failures during peer-to-peer recovery. Before disabling the `_recovery_source`, check with your OpenSearch cluster admin to determine whether your cluster performs regular flushes before starting the peer-to-peer recovery of shards before disabling the `_recovery_source`. +{: .warning} ## Search performance tuning Take the following steps to improve search performance: -* **Reduce segment count** +### Reduce segment count To improve search performance, you must keep the number of segments under control. Lucene's IndexSearcher searches over all of the segments in a shard to find the 'size' best results. @@ -56,7 +111,7 @@ Take the following steps to improve search performance: You can control the number of segments by choosing a larger refresh interval, or during indexing by asking OpenSearch to slow down segment creation by disabling the refresh interval. -* **Warm up the index** +### Warm up the index Native library indexes are constructed during indexing, but they're loaded into memory during the first search. In Lucene, each segment is searched sequentially (so, for k-NN, each segment returns up to k nearest neighbors of the query point), and the top 'size' number of results based on the score are returned from all the results returned by segments at a shard level (higher score = better result). @@ -77,13 +132,15 @@ Take the following steps to improve search performance: The warmup API operation loads all native library indexes for all shards (primary and replica) for the specified indexes into the cache, so there's no penalty to load native library indexes during initial searches. - **Note**: This API operation only loads the segments of the indexes it ***sees*** into the cache. If a merge or refresh operation finishes after the API runs, or if you add new documents, you need to rerun the API to load those native library indexes into memory. +This API operation only loads the segments of active indexes into the cache. If a merge or refresh operation finishes after the API runs, or if you add new documents, you need to rerun the API to load those native library indexes into memory. +{: .warning} + -* **Avoid reading stored fields** +### Avoid reading stored fields If your use case is simply to read the IDs and scores of the nearest neighbors, you can disable reading stored fields, which saves time retrieving the vectors from stored fields. -* **Use `mmap` file I/O** +### Use `mmap` file I/O For the Lucene-based approximate k-NN search, there is no dedicated cache layer that speeds up read/write operations. Instead, the plugin relies on the existing caching mechanism in OpenSearch core. In versions 2.4 and earlier of the Lucene-based approximate k-NN search, read/write operations were based on Java NIO by default, which can be slow, depending on the Lucene version and number of segments per shard. Starting with version 2.5, k-NN enables [`mmap`](https://en.wikipedia.org/wiki/Mmap) file I/O by default when the store type is `hybridfs` (the default store type in OpenSearch). This leads to fast file I/O operations and improves the overall performance of both data ingestion and search. The two file extensions specific to vector values that use `mmap` are `.vec` and `.vem`. For more information about these file extensions, see [the Lucene documentation](https://lucene.apache.org/core/9_0_0/core/org/apache/lucene/codecs/lucene90/Lucene90HnswVectorsFormat.html). diff --git a/_search-plugins/knn/radial-search-knn.md b/_search-plugins/knn/radial-search-knn.md index 04371c7cc3..48aaac034d 100644 --- a/_search-plugins/knn/radial-search-knn.md +++ b/_search-plugins/knn/radial-search-knn.md @@ -31,62 +31,7 @@ You can perform radial search with either the Lucene or Faiss engines. The follo ## Spaces -A space corresponds to the function used to measure the distance between two points in order to determine the k-nearest neighbors. When using k-NN, a lower score equates to a closer and better result. This is the opposite of how OpenSearch scores results, where a greater score equates to a better result. To convert distances to OpenSearch scores, radial search uses the following formula: 1 / (1 + distance). The k-NN plugin supports the following spaces. -Not every method supports each of these spaces. Be sure to refer to [the method documentation]({{site.url}}{{site.baseurl}}/search-plugins/knn/knn-index#method-definitions) to verify that the space you want to use is supported. -{: note.} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Space typeDistance function (d)OpenSearch score
l1\[ d(\mathbf{x}, \mathbf{y}) = \sum_{i=1}^n |x_i - y_i| \]\[ score = {1 \over 1 + d } \]
l2\[ d(\mathbf{x}, \mathbf{y}) = \sum_{i=1}^n (x_i - y_i)^2 \]\[ score = {1 \over 1 + d } \]
linf\[ d(\mathbf{x}, \mathbf{y}) = max(|x_i - y_i|) \]\[ score = {1 \over 1 + d } \]
cosinesimil\[ d(\mathbf{x}, \mathbf{y}) = 1 - cos { \theta } = 1 - {\mathbf{x} · \mathbf{y} \over \|\mathbf{x}\| · \|\mathbf{y}\|}\]\[ = 1 - - {\sum_{i=1}^n x_i y_i \over \sqrt{\sum_{i=1}^n x_i^2} · \sqrt{\sum_{i=1}^n y_i^2}}\] - where \(\|\mathbf{x}\|\) and \(\|\mathbf{y}\|\) represent the norms of vectors x and y respectively.nmslib and Faiss:\[ score = {1 \over 1 + d } \]
Lucene:\[ score = {2 - d \over 2}\]
innerproduct (supported for Lucene in OpenSearch version 2.13 and later)\[ d(\mathbf{x}, \mathbf{y}) = - {\mathbf{x} · \mathbf{y}} = - \sum_{i=1}^n x_i y_i \] -
Lucene: - \[ d(\mathbf{x}, \mathbf{y}) = {\mathbf{x} · \mathbf{y}} = \sum_{i=1}^n x_i y_i \] -
\[ \text{If} d \ge 0, \] \[score = {1 \over 1 + d }\] \[\text{If} d < 0, score = −d + 1\] -
Lucene: - \[ \text{If} d > 0, score = d + 1 \] \[\text{If} d \le 0\] \[score = {1 \over 1 + (-1 · d) }\] -
- -The cosine similarity formula does not include the `1 -` prefix. However, because similarity search libraries equate -lower scores with closer results, they return `1 - cosineSimilarity` for the cosine similarity space. This is why `1 -` is -included in the distance function. -{: .note } - -With cosine similarity, it is not valid to pass a zero vector (`[0, 0, ...]`) as an input. This is because the magnitude of -such a vector is 0, which raises a `divide by 0` exception in the corresponding formula. Requests -containing a zero vector will be rejected, and a corresponding exception will be thrown. -{: .note } +For supported spaces, see [Spaces]({{site.url}}{{site.baseurl}}/search-plugins/knn/approximate-knn/#spaces). ## Examples diff --git a/_search-plugins/neural-sparse-search.md b/_search-plugins/neural-sparse-search.md index fd86b3f6b0..b2b4fc33d6 100644 --- a/_search-plugins/neural-sparse-search.md +++ b/_search-plugins/neural-sparse-search.md @@ -4,6 +4,7 @@ title: Neural sparse search nav_order: 50 has_children: false redirect_from: + - /search-plugins/neural-sparse-search/ - /search-plugins/sparse-search/ --- @@ -30,6 +31,7 @@ To use neural sparse search, follow these steps: 1. [Create an index for ingestion](#step-2-create-an-index-for-ingestion). 1. [Ingest documents into the index](#step-3-ingest-documents-into-the-index). 1. [Search the index using neural search](#step-4-search-the-index-using-neural-sparse-search). +1. _Optional_ [Create and enable the two-phase processor](#step-5-create-and-enable-the-two-phase-processor-optional). ## Step 1: Create an ingest pipeline @@ -261,6 +263,38 @@ GET my-nlp-index/_search } } ``` +## Step 5: Create and enable the two-phase processor (Optional) + + +The `neural_sparse_two_phase_processor` is a new feature introduced in OpenSearch 2.15. Using the two-phase processor can significantly improve the performance of neural sparse queries. + +To quickly launch a search pipeline with neural sparse search, use the following example pipeline: + +```json +PUT /_search/pipeline/two_phase_search_pipeline +{ + "request_processors": [ + { + "neural_sparse_two_phase_processor": { + "tag": "neural-sparse", + "description": "This processor is making two-phase processor." + } + } + ] +} +``` +{% include copy-curl.html %} + +Then choose the index you want to configure with the search pipeline and set the `index.search.default_pipeline` to the pipeline name, as shown in the following example: +```json +PUT /index-name/_settings +{ + "index.search.default_pipeline" : "two_phase_search_pipeline" +} +``` +{% include copy-curl.html %} + + ## Setting a default model on an index or field @@ -390,4 +424,28 @@ The response contains both documents: ## Next steps -- To learn more about splitting long text into passages for neural search, see [Text chunking]({{site.url}}{{site.baseurl}}/search-plugins/text-chunking/). \ No newline at end of file +- To learn more about splitting long text into passages for neural search, see [Text chunking]({{site.url}}{{site.baseurl}}/search-plugins/text-chunking/). + +## FAQ + +Refer to the following frequently asked questions for more information about neural sparse search. + +### How do I mitigate remote connector throttling exceptions? + +When using connectors to call a remote service like SageMaker, ingestion and search calls sometimes fail due to remote connector throttling exceptions. + +To mitigate throttling exceptions, modify the connector's [`client_config`]({{site.url}}{{site.baseurl}}/ml-commons-plugin/remote-models/blueprints/#configuration-parameters) parameter to decrease the number of maximum connections, using the `max_connection` setting to prevent the maximum number of concurrent connections from exceeding the threshold of the remote service. You can also modify the retry settings to flatten the request spike during ingestion. + +For versions earlier than OpenSearch 2.15, the SageMaker throttling exception will be thrown as the following "error": + +``` + { + "type": "status_exception", + "reason": "Error from remote service: {\"message\":null}" + } +``` + + +## Next steps + +- To learn more about splitting long text into passages for neural search, see [Text chunking]({{site.url}}{{site.baseurl}}/search-plugins/text-chunking/). diff --git a/_search-plugins/search-pipelines/neural-sparse-query-two-phase-processor.md b/_search-plugins/search-pipelines/neural-sparse-query-two-phase-processor.md new file mode 100644 index 0000000000..53d69c1cc2 --- /dev/null +++ b/_search-plugins/search-pipelines/neural-sparse-query-two-phase-processor.md @@ -0,0 +1,150 @@ +--- +layout: default +title: Neural spare query two-phase processor +nav_order: 13 +parent: Search processors +grand_parent: Search pipelines +--- + +# Neural sparse query two-phase processor +Introduced 2.15 +{: .label .label-purple } + +The `neural_sparse_two_phase_processor` search processor is designed to provide faster search pipelines for [neural sparse search]({{site.url}}{{site.baseurl}}/search-plugins/neural-sparse-search/). It accelerates the neural sparse query by dividing the original method of scoring all documents with all tokens into two steps: + +1. High-weight tokens score the documents and filter out the top documents. +2. Low-weight tokens rescore the top documents. + +## Request fields + +The following table lists all available request fields. + +Field | Data type | Description +:--- | :--- | :--- +`enabled` | Boolean | Controls whether the two-phase processor is enabled. Default is `true`. +`two_phase_parameter` | Object | A map of key-value pairs representing the two-phase parameters and their associated values. You can specify the value of `prune_ratio`, `expansion_rate`, `max_window_size`, or any combination of these three parameters. Optional. +`two_phase_parameter.prune_ratio` | Float | A ratio that represents how to split the high-weight tokens and low-weight tokens. The threshold is the token's maximum score multiplied by its `prune_ratio`. Valid range is [0,1]. Default is `0.4` +`two_phase_parameter.expansion_rate` | Float | The rate at which documents will be fine-tuned during the second phase. The second-phase document number equals the query size (default is 10) multiplied by its expansion rate. Valid range is greater than 1.0. Default is `5.0` +`two_phase_parameter.max_window_size` | Int | The maximum number of documents that can be processed using the two-phase processor. Valid range is greater than 50. Default is `10000`. +`tag` | String | The processor's identifier. Optional. +`description` | String | A description of the processor. Optional. + +## Example + +The following example creates a search pipeline with a `neural_sparse_two_phase_processor` search request processor. + +### Create search pipeline + +The following example request creates a search pipeline with a `neural_sparse_two_phase_processor` search request processor. The processor sets a custom model ID at the index level and provides different default model IDs for two specific index fields: + +```json +PUT /_search/pipeline/two_phase_search_pipeline +{ + "request_processors": [ + { + "neural_sparse_two_phase_processor": { + "tag": "neural-sparse", + "description": "This processor is making two-phase processor.", + "enabled": true, + "two_phase_parameter": { + "prune_ratio": custom_prune_ratio, + "expansion_rate": custom_expansion_rate, + "max_window_size": custom_max_window_size + } + } + } + ] +} +``` +{% include copy-curl.html %} + +### Set search pipeline + +After the two-phase pipeline is created, set the `index.search.default_pipeline` setting to the name of the pipeline for the index on which you want to use the two-phase pipeline: + +```json +PUT /index-name/_settings +{ + "index.search.default_pipeline" : "two_phase_search_pipeline" +} +``` +{% include copy-curl.html %} + +## Limitation + +The `neural_sparse_two_phase_processor` has the following limitations. + +### Version support + +The `neural_sparse_two_phase_processor` can only be used with OpenSearch 2.15 or later. + +### Compound query support + +As of OpenSearch 2.15, only the Boolean [compound query]({{site.url}}{{site.baseurl}}/query-dsl/compound/index/) is supported. + +Neural sparse queries and Boolean queries with a boost parameter (not boosting queries) are also supported. + +## Examples + +The following examples show neural sparse queries with the supported query types. + +### Single neural sparse query + +``` +GET /my-nlp-index/_search +{ + "query": { + "neural_sparse": { + "passage_embedding": { + "query_text": "Hi world" + "model_id": + } + } + } +} +``` +{% include copy-curl.html %} + +### Neural sparse query nested in a Boolean query + +``` +GET /my-nlp-index/_search +{ + "query": { + "bool": { + "should": [ + { + "neural_sparse": { + "passage_embedding": { + "query_text": "Hi world", + "model_id": + }, + "boost": 2.0 + } + } + ] + } + } +} +``` +{% include copy-curl.html %} + +## P99 latency metrics +Using an OpenSearch cluster set up on three m5.4xlarge Amazon Elastic Compute Cloud (Amazon EC2) instances, OpenSearch conducts neural sparse query P99 latency tests on indexes corresponding to more than 10 datasets. + +### Doc-only mode latency metric + +In doc-only mode, the two-phase processor can significantly decrease query latency, as shown by the following latency metrics: + +- Average latency without the two-phase processor: 53.56 ms +- Average latency with the two-phase processor: 38.61 ms + +This results in an overall latency reduction of approximately 27.92%. Most indexes show a significant latency reduction when using the two-phase processor, with reductions ranging from 5.14 to 84.6%. The specific latency optimization values depend on the data distribution within the indexes. + +### Bi-encoder mode latency metric + +In bi-encoder mode, the two-phase processor can significantly decrease query latency, as shown by the following latency metrics: +- Average latency without the two-phase processor: 300.79 ms +- Average latency with the two-phase processor: 121.64 ms + +This results in an overall latency reduction of approximately 59.56%. Most indexes show a significant latency reduction when using the two-phase processor, with reductions ranging from 1.56 to 82.84%. The specific latency optimization values depend on the data distribution within the indexes. diff --git a/_search-plugins/search-relevance/compare-search-results.md b/_search-plugins/search-relevance/compare-search-results.md index 9e34b7cfd7..962442cd31 100644 --- a/_search-plugins/search-relevance/compare-search-results.md +++ b/_search-plugins/search-relevance/compare-search-results.md @@ -3,7 +3,7 @@ layout: default title: Comparing search results nav_order: 55 parent: Search relevance -has_children: true +has_children: false has_toc: false redirect_from: - /search-plugins/search-relevance/ diff --git a/_search-plugins/sql/identifiers.md b/_search-plugins/sql/identifiers.md index dc9c487c0f..214b2e53cb 100644 --- a/_search-plugins/sql/identifiers.md +++ b/_search-plugins/sql/identifiers.md @@ -4,6 +4,7 @@ title: Identifiers parent: SQL and PPL nav_order: 6 redirect_from: + - /observability-plugin/ppl/identifiers/ - /search-plugins/ppl/identifiers/ --- diff --git a/_search-plugins/sql/ppl/functions.md b/_search-plugins/sql/ppl/functions.md index 7ba18c29a9..275030f723 100644 --- a/_search-plugins/sql/ppl/functions.md +++ b/_search-plugins/sql/ppl/functions.md @@ -5,7 +5,8 @@ parent: PPL grand_parent: SQL and PPL nav_order: 2 redirect_from: - - /search-plugins/ppl/commands/ + - /observability-plugin/ppl/commands/ + - /search-plugins/ppl/commands/ --- # Commands diff --git a/_search-plugins/sql/ppl/syntax.md b/_search-plugins/sql/ppl/syntax.md index 3042902eb4..45eeb3aed2 100644 --- a/_search-plugins/sql/ppl/syntax.md +++ b/_search-plugins/sql/ppl/syntax.md @@ -1,71 +1,71 @@ ---- -layout: default -title: Syntax -parent: PPL -grand_parent: SQL and PPL -nav_order: 1 ---- - -# PPL syntax - -Every PPL query starts with the `search` command. It specifies the index to search and retrieve documents from. Subsequent commands can follow in any order. - -Currently, `PPL` supports only one `search` command, which can be omitted to simplify the query. -{ : .note} - -## Syntax - -```sql -search source= [boolean-expression] -source= [boolean-expression] -``` - -Field | Description | Required -:--- | :--- |:--- -`search` | Specifies search keywords. | Yes -`index` | Specifies which index to query from. | No -`bool-expression` | Specifies an expression that evaluates to a Boolean value. | No - -## Examples - -**Example 1: Search through accounts index** - -In the following example, the `search` command refers to an `accounts` index as the source and uses `fields` and `where` commands for the conditions: - -```sql -search source=accounts -| where age > 18 -| fields firstname, lastname -``` - -In the following examples, angle brackets `< >` enclose required arguments and square brackets `[ ]` enclose optional arguments. -{: .note } - - -**Example 2: Get all documents** - -To get all documents from the `accounts` index, specify it as the `source`: - -```sql -search source=accounts; -``` - -| account_number | firstname | address | balance | gender | city | employer | state | age | email | lastname | -:--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- -| 1 | Amber | 880 Holmes Lane | 39225 | M | Brogan | Pyrami | IL | 32 | amberduke@pyrami.com | Duke -| 6 | Hattie | 671 Bristol Street | 5686 | M | Dante | Netagy | TN | 36 | hattiebond@netagy.com | Bond -| 13 | Nanette | 789 Madison Street | 32838 | F | Nogal | Quility | VA | 28 | null | Bates -| 18 | Dale | 467 Hutchinson Court | 4180 | M | Orick | null | MD | 33 | daleadams@boink.com | Adams - -**Example 3: Get documents that match a condition** - -To get all documents from the `accounts` index that either have `account_number` equal to 1 or have `gender` as `F`, use the following query: - -```sql -search source=accounts account_number=1 or gender=\"F\"; -``` - -| account_number | firstname | address | balance | gender | city | employer | state | age | email | lastname | -:--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- -| 1 | Amber | 880 Holmes Lane | 39225 | M | Brogan | Pyrami | IL | 32 | amberduke@pyrami.com | Duke | -| 13 | Nanette | 789 Madison Street | 32838 | F | Nogal | Quility | VA | 28 | null | Bates | +--- +layout: default +title: Syntax +parent: PPL +grand_parent: SQL and PPL +nav_order: 1 +--- + +# PPL syntax + +Every PPL query starts with the `search` command. It specifies the index to search and retrieve documents from. Subsequent commands can follow in any order. + +Currently, `PPL` supports only one `search` command, which can be omitted to simplify the query. +{ : .note} + +## Syntax + +```sql +search source= [boolean-expression] +source= [boolean-expression] +``` + +Field | Description | Required +:--- | :--- |:--- +`search` | Specifies search keywords. | Yes +`index` | Specifies which index to query from. | No +`bool-expression` | Specifies an expression that evaluates to a Boolean value. | No + +## Examples + +**Example 1: Search through accounts index** + +In the following example, the `search` command refers to an `accounts` index as the source and uses `fields` and `where` commands for the conditions: + +```sql +search source=accounts +| where age > 18 +| fields firstname, lastname +``` + +In the following examples, angle brackets `< >` enclose required arguments and square brackets `[ ]` enclose optional arguments. +{: .note } + + +**Example 2: Get all documents** + +To get all documents from the `accounts` index, specify it as the `source`: + +```sql +search source=accounts; +``` + +| account_number | firstname | address | balance | gender | city | employer | state | age | email | lastname | +:--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- +| 1 | Amber | 880 Holmes Lane | 39225 | M | Brogan | Pyrami | IL | 32 | amberduke@pyrami.com | Duke +| 6 | Hattie | 671 Bristol Street | 5686 | M | Dante | Netagy | TN | 36 | hattiebond@netagy.com | Bond +| 13 | Nanette | 789 Madison Street | 32838 | F | Nogal | Quility | VA | 28 | null | Bates +| 18 | Dale | 467 Hutchinson Court | 4180 | M | Orick | null | MD | 33 | daleadams@boink.com | Adams + +**Example 3: Get documents that match a condition** + +To get all documents from the `accounts` index that either have `account_number` equal to 1 or have `gender` as `F`, use the following query: + +```sql +search source=accounts account_number=1 or gender=\"F\"; +``` + +| account_number | firstname | address | balance | gender | city | employer | state | age | email | lastname | +:--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- +| 1 | Amber | 880 Holmes Lane | 39225 | M | Brogan | Pyrami | IL | 32 | amberduke@pyrami.com | Duke | +| 13 | Nanette | 789 Madison Street | 32838 | F | Nogal | Quility | VA | 28 | null | Bates | diff --git a/_search-plugins/sql/sql/basic.md b/_search-plugins/sql/sql/basic.md index 8878f3bb27..fca14ae870 100644 --- a/_search-plugins/sql/sql/basic.md +++ b/_search-plugins/sql/sql/basic.md @@ -4,7 +4,7 @@ title: Basic Queries parent: SQL grand_parent: SQL and PPL nav_order: 5 -Redirect_from: +redirect_from: - /search-plugins/sql/basic/ --- diff --git a/_search-plugins/sql/sql/complex.md b/_search-plugins/sql/sql/complex.md index c70b965870..ecd52d19c2 100644 --- a/_search-plugins/sql/sql/complex.md +++ b/_search-plugins/sql/sql/complex.md @@ -4,7 +4,7 @@ title: Complex Queries parent: SQL grand_parent: SQL and PPL nav_order: 6 -Redirect_from: +redirect_from: - /search-plugins/sql/complex/ --- diff --git a/_search-plugins/sql/sql/delete.md b/_search-plugins/sql/sql/delete.md index 41cb6705af..eef810e7f5 100644 --- a/_search-plugins/sql/sql/delete.md +++ b/_search-plugins/sql/sql/delete.md @@ -4,7 +4,7 @@ title: Delete parent: SQL grand_parent: SQL and PPL nav_order: 12 -Redirect_from: +redirect_from: - /search-plugins/sql/delete/ --- diff --git a/_search-plugins/sql/sql/functions.md b/_search-plugins/sql/sql/functions.md index 03b808243c..19d29a9143 100755 --- a/_search-plugins/sql/sql/functions.md +++ b/_search-plugins/sql/sql/functions.md @@ -4,8 +4,9 @@ title: Functions parent: SQL grand_parent: SQL and PPL nav_order: 7 -Redirect_from: - - /search-plugins/sql/functions/ +redirect_from: + - /search-plugins/ppl/commands/ + - /observability-plugin/ppl/commands/ --- # Functions diff --git a/_search-plugins/sql/sql/index.md b/_search-plugins/sql/sql/index.md index 7035b6d664..6b2cee24da 100644 --- a/_search-plugins/sql/sql/index.md +++ b/_search-plugins/sql/sql/index.md @@ -7,7 +7,6 @@ has_children: true has_toc: false redirect_from: - /search-plugins/sql/sql/index/ - --- # SQL diff --git a/_security-analytics/api-tools/correlation-eng.md b/_security-analytics/api-tools/correlation-eng.md index 81f73315a9..c2a6ca56b1 100644 --- a/_security-analytics/api-tools/correlation-eng.md +++ b/_security-analytics/api-tools/correlation-eng.md @@ -5,19 +5,20 @@ parent: API tools nav_order: 55 --- - # Correlation engine APIs Correlation engine APIs allow you to create new correlation rules, view findings and correlations within a certain time window, and perform other tasks. --- + ## Create correlation rules between log types -This API is used to create correlation rules: +You can use the following API to create correlation rules: ```json POST /_plugins/_security_analytics/correlation/rules ``` +{% include copy-curl.html %} ### Request fields @@ -91,6 +92,7 @@ POST /_plugins/_security_analytics/correlation/rules } } ``` +{% include copy-curl.html %} ### Response fields @@ -99,13 +101,15 @@ POST /_plugins/_security_analytics/correlation/rules | `_id` | String | The Id for the new rule. | --- -## List all findings and their correlations within a time window -This API provides a list of all findings and their correlations within a specified time window: +## List all findings and correlations within a certain time window + +You can use the following API to list all findings and their correlations within a certain time window: ```json GET /_plugins/_security_analytics/correlations?start_timestamp=&end_timestamp= ``` +{% include copy-curl.html %} ### Query parameters @@ -138,6 +142,7 @@ GET /_plugins/_security_analytics/correlations?start_timestamp=1689289210000&end ] } ``` +{% include copy-curl.html %} ### Response fields @@ -150,13 +155,15 @@ GET /_plugins/_security_analytics/correlations?start_timestamp=1689289210000&end | `rules` | Array | A list of correlation rule IDs associated with the correlated findings. | --- + ## List correlations for a finding belonging to a log type -This API is used to list correlations for specific findings and the log types associated with them: +You can use the following API to list correlations for certain findings and associated log types: ```json GET /_plugins/_security_analytics/findings/correlate?finding=425dce0b-f5ee-4889-b0c0-7d15669f0871&detector_type=ad_ldap&nearby_findings=20&time_window=10m ``` +{% include copy-curl.html %} ### Query parameters @@ -167,7 +174,6 @@ GET /_plugins/_security_analytics/findings/correlate?finding=425dce0b-f5ee-4889- | `nearby_findings` | Number | The number of nearby findings with respect to the given finding Id. | | `time_window` | String | Sets a time window in which all of the correlations must have occurred together. | - #### Example request ```json @@ -213,6 +219,7 @@ GET /_plugins/_security_analytics/findings/correlate?finding=425dce0b-f5ee-4889- ] } ``` +{% include copy-curl.html %} ### Response fields @@ -222,3 +229,136 @@ GET /_plugins/_security_analytics/findings/correlate?finding=425dce0b-f5ee-4889- | `detector_type` | String | The log type associated with the finding. | | `score` | Number | The correlation score for the correlated finding. The score is based on the proximity of relevant findings in the threat scenario defined by the correlation rule. | +## List correlation alerts + +You can use the following API to list correlation alerts: + +```json +GET /_plugins/_security_analytics/correlationAlerts +``` +{% include copy-curl.html %} + +### Query parameters + +| Parameter | Type | Description | +| :--- | :--- |:--- | +| `correlation_rule_id` | String | The correlation rule ID. | Optional + +#### Example request + +```json +GET /_plugins/_security_analytics/correlations?correlation_rule_id=VjY0MpABPzR_pcEveVRq +``` +{% include copy-curl.html %} + +#### Example response + +```json +{ + "correlationAlerts": [ + { + "correlated_finding_ids": [ + "4f867df9-c9cb-4dc1-84bb-6c8b575f1a54" + ], + "correlation_rule_id": "VjY0MpABPzR_pcEveVRq", + "correlation_rule_name": "rule-corr", + "user": null, + "id": "8532c08b-3ab5-4e95-a1c2-5884c4cd41a5", + "version": 1, + "schema_version": 1, + "trigger_name": "trigger1", + "state": "ACTIVE", + "error_message": null, + "severity": "1", + "action_execution_results": [], + "start_time": "2024-06-19T20:37:08.257Z", + "end_time": "2024-06-19T20:42:08.257Z", + "acknowledged_time": null + }, + { + "correlated_finding_ids": [ + "30d2109f-76bb-44ad-8f68-6daa905e018d" + ], + "correlation_rule_id": "VjY0MpABPzR_pcEveVRq", + "correlation_rule_name": "rule-corr", + "user": null, + "id": "8bba85d9-a7fc-4c87-b35e-a7236b87159f", + "version": 1, + "schema_version": 1, + "trigger_name": "trigger1", + "state": "ACTIVE", + "error_message": null, + "severity": "1", + "action_execution_results": [], + "start_time": "2024-06-19T20:43:08.208Z", + "end_time": "2024-06-19T20:48:08.208Z", + "acknowledged_time": null + } + ], + "total_alerts": 2 +} +``` +{% include copy-curl.html %} + +## Acknowledge correlation alerts + +You can use the following API to acknowledge the correlation alerts. + +### Example request + +```json +POST /_plugins/_security_analytics/_acknowledge/correlationAlerts +{ + "alertIds": ["8532c08b-3ab5-4e95-a1c2-5884c4cd41a5", "8bba85d9-a7fc-4c87-b35e-a7236b87159f"] +} +``` +{% include copy-curl.html %} + +#### Example response + +```json +{ + "acknowledged": [ + { + "correlated_finding_ids": [ + "4f867df9-c9cb-4dc1-84bb-6c8b575f1a54" + ], + "correlation_rule_id": "VjY0MpABPzR_pcEveVRq", + "correlation_rule_name": "rule-corr", + "user": null, + "id": "8532c08b-3ab5-4e95-a1c2-5884c4cd41a5", + "version": 1, + "schema_version": 1, + "trigger_name": "trigger1", + "state": "ACTIVE", + "error_message": null, + "severity": "1", + "action_execution_results": [], + "start_time": "2024-06-19T20:37:08.257Z", + "end_time": "2024-06-19T20:42:08.257Z", + "acknowledged_time": null + }, + { + "correlated_finding_ids": [ + "30d2109f-76bb-44ad-8f68-6daa905e018d" + ], + "correlation_rule_id": "VjY0MpABPzR_pcEveVRq", + "correlation_rule_name": "rule-corr", + "user": null, + "id": "8bba85d9-a7fc-4c87-b35e-a7236b87159f", + "version": 1, + "schema_version": 1, + "trigger_name": "trigger1", + "state": "ACTIVE", + "error_message": null, + "severity": "1", + "action_execution_results": [], + "start_time": "2024-06-19T20:43:08.208Z", + "end_time": "2024-06-19T20:48:08.208Z", + "acknowledged_time": null + } + ], + "failed": [] +} +``` +{% include copy-curl.html %} diff --git a/_security-analytics/usage/alerts.md b/_security-analytics/usage/alerts.md index a4a4541f09..9e1f00c3c4 100644 --- a/_security-analytics/usage/alerts.md +++ b/_security-analytics/usage/alerts.md @@ -7,41 +7,53 @@ nav_order: 46 # Working with alerts -The Alerts window includes features for viewing and working with alerts. The two main features are: -* The bar graph with alert information arranged by count, date, and alert status or alert severity. -* The Alerts list arranged by time of the alert, the alert's trigger name, which detector triggered it, and other details. +The **Alerts** window provides features for viewing and managing alerts. It consists of: -You can select the **Refresh** button at any time to refresh information on the Alerts page. +- A bar graph displaying alert counts, dates, and statuses or severities. +- Two tabs: + - **Findings**: Lists detector-generated alerts, showing details such as alert time, trigger name, and the detector that triggered the alert. + - **Correlations**: Lists correlation-rule-generated alerts, showing details such as alert time, trigger name, and the correlation rule that triggered the alert. + +You can select the **Refresh** button to refresh information on the **Alerts** page. --- -## The Alerts graph -The Alerts graph can display alerts by their status or severity. Use the **Group by** dropdown list to specify either Alert status or Alert severity. +## Alerts graph + +The **Alerts** graph displays alerts by their status or severity. Use the **Group by** dropdown menu to specify either **Alert status** or **Alert severity**. -To specify the date range you would like the graph to display, first select the calendar dropdown arrow. The date selector window opens. +To specify a date range, select the calendar icon to activate the dropdown menu. The date selector window opens. An example window is shown in the following image.
Date selector for findings graph -You can use the **Quick select** settings to specify an exact window of time. -* Select either **Last** or **Next** in the first dropdown list to set the window of time behind the current setting or ahead of the current setting. -* Select a number in the second dropdown list to define a value for the range. -* Select a unit of time in the third dropdown list. Available options are seconds, minutes, hours, days, weeks, months, and years. -Select the **Apply** button to apply the range of dates to the graph. Information on the graph changes accordingly. +You can use the **Quick select** settings to specify a date range: +* Select either **Last** or **Next** from the first dropdown menu to set the date range to either behind the current setting or ahead of the current setting. +* Select a number from the second dropdown menu to define a value for the range. +* Select a unit of time from the third dropdown menu. Available options are seconds, minutes, hours, days, weeks, months, and years. +* Select the **Apply** button to apply the time range to the graph. The graph is immediately updated. + +An example window is shown in the following image. Quick select settings example -You can use the left and right arrows to move the window of time behind the current range of dates or ahead of the current range of dates. When you use these arrows, the start date and end date appear in the date range field. You can then select each one to set an absolute, relative, or current date and time. For absolute and relative changes, select the **Update** button to apply the changes. +You can use the left and right arrows in the upper-left corner to shift the time range backward or forward, respectively. When you use these arrows, the start date and end date appear in the date range field. You can then select each one to set an absolute, relative, or current date and time. For absolute and relative changes, select the **Update** button to apply the changes. + +An example window is shown in the following image. Altering date range -As an alternative, you can select an option in the **Commonly used** section (see the preceding image of the calendar dropdown list) to conveniently set a window of time. Options include date ranges such as **Today**, **Yesterday**, **this week**, and **week to date**. +As an alternative, you can select an option in the **Commonly used** section (see the preceding image of the calendar dropdown menu) to conveniently set a date range. Options include **Today**, **Yesterday**, **this week**, and **week to date**. -When one of the commonly used windows of time is selected, you can select the **Show dates** label in the date range field to populate the range of dates. Following that, you can select either the start date or end date to specify by an absolute, relative, or current date and time setting. For absolute and relative changes, select the **Update** button to apply the changes. +When a commonly used date range is selected, you can select the **Show dates** label in the date range field to populate the ranges. You can then select either the start date or end date to specify an absolute, relative, or current date and time setting. For absolute and relative changes, select the **Update** button to apply the changes. -As one more alternative, you can select an option from the **Recently used date ranges** section to go back to a previous setting. +You can also select an option from the **Recently used date ranges** section to revert to a previous setting. --- -## The Alerts list -The Alerts list displays all findings according to the time when the alert was triggered, the alert's trigger name, the detector that triggered the alert, the alert status, and alert severity. -Use the **Alert severity** dropdown list to filter the list of alerts by severity. Use the **Status** dropdown list to filter the list by alert status. +## Alerts list + +The **Alerts list** displays all alerts, with two tabs for different types of alerts: + +- **Findings**: The **Alerts list** displays all findings according to the time when the alert was triggered, the alert's trigger name, the detector that triggered the alert, the alert status, and the alert severity. +- **Correlations**: The **Alerts list** displays all correlations, including the correlation rule and time window, the alert's trigger name, the correlation rule name that triggered the alert, the alert status, and the alert severity. +Use the **Alert severity** dropdown menu to filter the list of alerts by severity. Use the **Status** dropdown menu to filter the list by alert status. diff --git a/_security/access-control/api.md b/_security/access-control/api.md index bea080a078..63717d621a 100644 --- a/_security/access-control/api.md +++ b/_security/access-control/api.md @@ -815,18 +815,24 @@ Creates, updates, or deletes multiple roles in a single call. PATCH _plugins/_security/api/roles [ { - "op": "replace", "path": "/role1/index_permissions/0/fls", "value": ["test1", "test2"] + "op": "replace", "path": "/role1/index_permissions/0/fls", "value": ["myfield*", "~myfield1"] }, { "op": "remove", "path": "/role1/index_permissions/0/dls" }, { - "op": "add", "path": "/role2/cluster_permissions", "value": ["manage_snapshots"] + "op": "add", "path": "/role2/cluster_permissions/-", "value": { + "index_patterns": ["test_index"], + "allowed_actions": ["indices:data/read/scroll/clear"] + } } ] ``` {% include copy-curl.html %} +You can use `-` to insert a new permission to the end of the array of permissions. +{: .note} + #### Example response ```json @@ -1005,6 +1011,98 @@ PATCH _plugins/_security/api/rolesmapping } ``` +--- + +## Allowlist + +### Get allowlist + +Retrieves the current `allowlist` configuration. + +#### Request + +```json +GET _plugins/_security/api/allowlist +``` +{% include copy-curl.html %} + +#### Example response + +```json +{ + "config" : { + "enabled" : true, + "requests" : { + "/_cat/nodes" : [ + "GET" + ], + "/_cat/indices" : [ + "GET" + ], + "/_plugins/_security/whoami" : [ + "GET" + ] + } + } +} +``` + +### Create allowlist + +Creates an `allowlist` configuration. + +#### Request + +```json +PUT _plugins/_security/api/allowlist +{ + "enabled": true, + "requests": { + "/_cat/nodes": ["GET"], + "/_cat/indices": ["GET"], + "/_plugins/_security/whoami": ["GET"] + } +} +``` +{% include copy-curl.html %} + +#### Example response + +```json +{ + "status":"OK", + "message":"'config' updated." +} +``` + +### Update allowlist + +Updates an `allowlist` configuration. + +#### Request + +```json +PATCH _plugins/_security/api/allowlist +[ + { + "op": "add", + "path": "/config/requests", + "value": { + "/_cat/nodes": ["POST"] + } + } +] +``` +{% include copy-curl.html %} + +#### Example response + +```json +{ + "status":"OK", + "message":"Resource updated." +} +``` --- diff --git a/_security/access-control/field-masking.md b/_security/access-control/field-masking.md index c672e75d04..188def5a6c 100644 --- a/_security/access-control/field-masking.md +++ b/_security/access-control/field-masking.md @@ -12,7 +12,7 @@ redirect_from: If you don't want to remove fields from a document using [field-level security]({{site.url}}{{site.baseurl}}/security/access-control/field-level-security/), you can mask their values. Currently, field masking is only available for string-based fields and replaces the field's value with a cryptographic hash. -Field masking works alongside field-level security on the same per-role, per-index basis. You can allow certain roles to see sensitive fields in plain text and mask them for others. A search result with a masked field might look like this: +Field masking works alongside field-level security on the same per-role, per-index basis. You can allow certain roles to see sensitive fields in plain text and mask them for others. A search result with a masked field might look like the following: ```json { @@ -28,19 +28,20 @@ Field masking works alongside field-level security on the same per-role, per-ind ``` -## Set the salt +## Set the salt setting -You set the salt (a random string used to hash your data) in `opensearch.yml`: +You can set the salt (a random string used to hash your data) in `opensearch.yml` using the optional `plugins.security.compliance.salt` setting. The salt value must fullfil the following requirements: + +- Must be at least 32 characters. +- Use only ASCII characters. + +The following example shows a salt value: ```yml plugins.security.compliance.salt: abcdefghijklmnopqrstuvqxyz1234567890 ``` -Property | Description -:--- | :--- -`plugins.security.compliance.salt` | The salt to use when generating the hash value. Must be at least 32 characters. Only ASCII characters are allowed. Optional. - -Setting the salt is optional, but we highly recommend it. +Although setting the salt is optional, it is highly recommended. ## Configure field masking @@ -78,7 +79,14 @@ See [Create role]({{site.url}}{{site.baseurl}}/security/access-control/api/#crea By default, the Security plugin uses the BLAKE2b algorithm, but you can use any hashing algorithm that your JVM provides. This list typically includes MD5, SHA-1, SHA-384, and SHA-512. -To specify a different algorithm, add it after the masked field: +You can override the default algorithm in `opensearch.yml` using the option default masking algorithm setting `plugins.security.masked_fields.algorithm.default`, as shown in the following example: + +```yml +plugins.security.masked_fields.algorithm.default: SHA-256 +``` +. + +To specify a different algorithm, add it after the masked field in `roles.yml`, as shown in the following: ```yml someonerole: @@ -95,7 +103,7 @@ someonerole: ## (Advanced) Pattern-based field masking -Rather than creating a hash, you can use one or more regular expressions and replacement strings to mask a field. The syntax is `:://::`. If you use multiple regular expressions, the results are passed from left to right, like piping in a shell: +Rather than creating a hash, you can use one or more regular expressions and replacement strings to mask a field. The syntax is `:://::`. If you use multiple regular expressions, the results are passed from left to right, like piping in a shell, as shown in the following example: ```yml hr_employee: diff --git a/_security/access-control/index.md b/_security/access-control/index.md index ae433ed31e..8123e2e25f 100644 --- a/_security/access-control/index.md +++ b/_security/access-control/index.md @@ -22,7 +22,7 @@ Term | Description Permission | An individual action, such as creating an index (e.g. `indices:admin/create`). For a complete list, see [Permissions]({{site.url}}{{site.baseurl}}/security/access-control/permissions/). Action group | A set of permissions. For example, the predefined `SEARCH` action group authorizes roles to use the `_search` and `_msearch` APIs. Role | Security roles define the scope of a permission or action group: cluster, index, document, or field. For example, a role named `delivery_analyst` might have no cluster permissions, the `READ` action group for all indexes that match the `delivery-data-*` pattern, access to all document types within those indexes, and access to all fields except `delivery_driver_name`. -Backend role | (Optional) Arbitrary strings that you specify *or* that come from an external authentication system (for example, LDAP/Active Directory). Backend roles can help simplify the role mapping process. Rather than mapping a role to 100 individual users, you can map the role to a single backend role that all 100 users share. +Backend role | (Optional) A backend role is a specific identifier assigned to a user or group of users by an external authentication system such as LDAP/Active Directory. Instead of mapping permissions to individual users, you can assign these permissions to backend roles, which can significantly streamline the role mapping process. For example, if 100 users within an organization share a common function, they can all be assigned the same backend role. With this approach you only need to map the role to the backend role identifier, rather than map to each user individually. User | Users make requests to OpenSearch clusters. A user has credentials (e.g. a username and password), zero or more backend roles, and zero or more custom attributes. Role mapping | Users assume roles after they successfully authenticate. Role mappings map roles to users (or backend roles). For example, a mapping of `kibana_user` (role) to `jdoe` (user) means that John Doe gains all the permissions of `kibana_user` after authenticating. Likewise, a mapping of `all_access` (role) to `admin` (backend role) means that any user with the backend role of `admin` gains all the permissions of `all_access` after authenticating. You can map each role to multiple users and/or backend roles. diff --git a/_security/access-control/permissions.md b/_security/access-control/permissions.md index a13814c1ee..5a75a0a5a7 100644 --- a/_security/access-control/permissions.md +++ b/_security/access-control/permissions.md @@ -182,6 +182,26 @@ Cross-references to API documentation in the permissions that follow are only in {: .note } +### Cluster wide index permissions + +| **Permission** | **Description** | +| :--- | :--- | +| `indices:admin/template/delete` | Permission to [delete index templates]({{site.url}}{{site.baseurl}}/im-plugin/index-templates/#delete-a-template). | +| `indices:admin/template/get` | Permission to [get index templates]({{site.url}}{{site.baseurl}}/im-plugin/index-templates/#retrieve-a-template). | +| `indices:admin/template/put` | Permission to [create index templates]({{site.url}}{{site.baseurl}}/im-plugin/index-templates/#create-a-template). | +| `indices:data/read/scroll` | Permission to scroll through data. This setting must be configured as both a cluster- and index-level permission. | +| `indices:data/read/scroll/clear` | Permission to clear the scroll object. This setting must be configured as both a cluster- and index-level permission. | +| `indices:data/read/mget` | Permission to run [multiple GET operations]({{site.url}}{{site.baseurl}}/api-reference/document-apis/multi-get/) in one request. | +| `indices:data/read/mget*` | Permission to run multiple GET operations in one request. This setting must be configured as both a cluster- and index-level permission. | +| `indices:data/read/msearch` | Permission to run [multiple search]({{site.url}}{{site.baseurl}}/api-reference/multi-search/) requests in a single API request. This setting must be configured as both a cluster- and index-level permission. | +| `indices:data/read/msearch/template` | Permission to bundle [multiple search templates]({{site.url}}{{site.baseurl}}/api-reference/search-template/#multiple-search-templates) and send them to your OpenSearch cluster in a single request. This setting must be configured as both a cluster- and index-level permission. | +| `indices:data/read/mtv` | Permission to retrieve multiple term vectors with a single request. This setting must be configured as both a cluster- and index-level permission. | +| `indices:data/read/mtv*` | Permission to retrieve multiple term vectors with a single request. This setting must be configured as both a cluster- and index-level permission. | +| `indices:data/read/search/template/render` | Permission to render search templates. This setting must be configured as both a cluster- and index-level permission. | +| `indices:data/write/bulk` | Permission to run a [bulk]({{site.url}}{{site.baseurl}}/api-reference/document-apis/bulk/) request. This setting must be configured as both a cluster- and index-level permission. | +| `indices:data/write/bulk*` | Permission to run a bulk request. This setting must be configured as both a cluster- and index-level permission. | +| `indices:data/write/reindex` | Permission to run a [reindex]({{site.url}}{{site.baseurl}}/im-plugin/reindex-data/) operation. | + ### Ingest API permissions See [Ingest APIs]({{site.url}}{{site.baseurl}}/api-reference/ingest-apis/index/). @@ -232,6 +252,7 @@ See [Alerting API]({{site.url}}{{site.baseurl}}/observing-your-data/alerting/api - cluster:admin/opendistro/alerting/monitor/get - cluster:admin/opendistro/alerting/monitor/search - cluster:admin/opendistro/alerting/monitor/write +- cluster:admin/opensearch/alerting/remote/indexes/get ### Asynchronous Search permissions @@ -476,9 +497,6 @@ These permissions apply to an index or index pattern. You might want a user to h | `indices:admin/seq_no/global_checkpoint_sync` | Permission to perform a global checkpoint sync. | | `indices:admin/settings/update` | Permission to [update index settings]({{site.url}}{{site.baseurl}}/api-reference/index-apis/update-settings/). | | `indices:admin/shards/search_shards` | Permission to perform [cross cluster search]({{site.url}}{{site.baseurl}}/security/access-control/cross-cluster-search/). | -| `indices:admin/template/delete` | Permission to [delete index templates]({{site.url}}{{site.baseurl}}/im-plugin/index-templates/#delete-a-template). | -| `indices:admin/template/get` | Permission to [get index templates]({{site.url}}{{site.baseurl}}/im-plugin/index-templates/#retrieve-a-template). | -| `indices:admin/template/put` | Permission to [create index templates]({{site.url}}{{site.baseurl}}/im-plugin/index-templates/#create-a-template). | | `indices:admin/upgrade` | Permission for administrators to perform upgrades. | | `indices:admin/validate/query` | Permission to validate a specific query. | | `indices:data/read/explain` | Permission to run the [Explain API]({{site.url}}{{site.baseurl}}/api-reference/explain/). | @@ -486,26 +504,25 @@ These permissions apply to an index or index pattern. You might want a user to h | `indices:data/read/field_caps*` | Permission to run the Field Capabilities API. | | `indices:data/read/get` | Permission to read index data. | | `indices:data/read/mget` | Permission to run [multiple GET operations]({{site.url}}{{site.baseurl}}/api-reference/document-apis/multi-get/) in one request. | -| `indices:data/read/mget*` | Permission to run multiple GET operations in one request. | -| `indices:data/read/msearch` | Permission to run [multiple search]({{site.url}}{{site.baseurl}}/api-reference/multi-search/) requests into a single request. | -| `indices:data/read/msearch/template` | Permission to bundle [multiple search templates]({{site.url}}{{site.baseurl}}/api-reference/search-template/#multiple-search-templates) and send them to your OpenSearch cluster in a single request. | -| `indices:data/read/mtv` | Permission to retrieve multiple term vectors with a single request. | -| `indices:data/read/mtv*` | Permission to retrieve multiple term vectors with a single request. | +| `indices:data/read/mget*` | Permission to run multiple GET operations in one request. This setting must be configured as both a cluster- and index-level permission. | +| `indices:data/read/msearch` | Permission to run [multiple search]({{site.url}}{{site.baseurl}}/api-reference/multi-search/) requests in a single request. This setting must be configured as both a cluster- and index-level permission. | +| `indices:data/read/msearch/template` | Permission to bundle [multiple search templates]({{site.url}}{{site.baseurl}}/api-reference/search-template/#multiple-search-templates) and send them to your OpenSearch cluster in a single request. This setting must be configured as both a cluster- and index-level permission. | +| `indices:data/read/mtv` | Permission to retrieve multiple term vectors with a single request. This setting must be configured as both a cluster- and index-level permission. | +| `indices:data/read/mtv*` | Permission to retrieve multiple term vectors with a single request. This setting must be configured as both a cluster- and index-level permission. | | `indices:data/read/plugins/replication/file_chunk` | Permission to check files during segment replication. | | `indices:data/read/plugins/replication/changes` | Permission to make changes to segment replication settings. | -| `indices:data/read/scroll` | Permission to scroll data. | -| `indices:data/read/scroll/clear` | Permission to clear read scroll data. | +| `indices:data/read/scroll` | Permission to scroll through data. This setting must be configured as both a cluster- and index-level permission. | +| `indices:data/read/scroll/clear` | Permission to clear the scroll object. This setting must be configured as both a cluster- and index-level permission. | | `indices:data/read/search` | Permission to [search]({{site.url}}{{site.baseurl}}/api-reference/search/) data. | | `indices:data/read/search*` | Permission to search data. | | `indices:data/read/search/template` | Permission to read a search template. | | `indices:data/read/tv` | Permission to retrieve information and statistics for terms in the fields of a particular document. | -| `indices:data/write/bulk` | Permission to run a [bulk]({{site.url}}{{site.baseurl}}/api-reference/document-apis/bulk/) request. | -| `indices:data/write/bulk*` | Permission to run a bulk request. | | `indices:data/write/delete` | Permission to [delete documents]({{site.url}}{{site.baseurl}}/api-reference/document-apis/delete-document/). | | `indices:data/write/delete/byquery` | Permission to delete all documents that [match a query]({{site.url}}{{site.baseurl}}/api-reference/document-apis/delete-by-query/). | | `indices:data/write/plugins/replication/changes` | Permission to change data replication configurations and settings within indexes. | +| `indices:data/write/bulk` | Permission to run a [bulk]({{site.url}}{{site.baseurl}}/api-reference/document-apis/bulk/) request. This setting must be configured as both a cluster- and index-level permission. | +| `indices:data/write/bulk*` | Permission to run a bulk request. This setting must be configured as both a cluster- and index-level permission. | | `indices:data/write/index` | Permission to add documents to existing indexes. See also [Index document]( {{site.url}}{{site.baseurl}}/api-reference/document-apis/index-document/ ). | -| `indices:data/write/reindex` | Permission to run a [reindex]({{site.url}}{{site.baseurl}}/im-plugin/reindex-data/). | | `indices:data/write/update` | Permission to update an index. | | `indices:data/write/update/byquery` | Permission to run the script to update all of the documents that [match the query]({{site.url}}{{site.baseurl}}/api-reference/document-apis/update-by-query/). | | `indices:monitor/data_stream/stats` | Permission to stream stats. | diff --git a/_security/access-control/users-roles.md b/_security/access-control/users-roles.md index 9faafcc008..b6157bf2d9 100644 --- a/_security/access-control/users-roles.md +++ b/_security/access-control/users-roles.md @@ -100,7 +100,7 @@ See [YAML files]({{site.url}}{{site.baseurl}}/security/configuration/yaml/#roles ### REST API -See [Create role]({{site.url}}{{site.baseurl}}/security/access-control/api/#create-role). +See [Patch role]({{site.url}}{{site.baseurl}}/security/access-control/api/#patch-role). ## Mapping users to roles @@ -242,3 +242,42 @@ Map the role to your user: 1. Choose the **Mapped users** tab and **Manage mapping**. 1. For **Internal users**, add your bulk access user. 1. Choose **Map**. + +## Admin and super admin roles + +OpenSearch user roles are essential for controlling access to cluster resources. Users can be categorized as regular users, admin users, or super admin users based on their access rights and responsibilities. + +For more information about defining users, see [Defining users](https://opensearch.org/docs/latest/security/access-control/users-roles/#defining-users). For more information about defining roles, see [Defining roles](https://opensearch.org/docs/latest/security/access-control/users-roles/#defining-roles). + + +### Regular users +Regular users have basic access permissions that allow them to interact with the OpenSearch cluster, such as querying data and using dashboards, but they do not have administrative privileges. + +### Admin users +Admin users have elevated permissions that allow them to perform various administrative tasks within the cluster. They have broader access compared to regular users, including permissions to: +- Manage users and roles. +- Configure permissions. +- Adjust backend settings. + +Admin users can perform these tasks by configuring settings in the `opensearch.yml` file, using OpenSearch Dashboards, or interacting with the REST API. For more information about configuring users and roles, see [predefined roles](https://opensearch.org/docs/latest/security/access-control/users-roles/#predefined-roles). + +### Super admin users +Super admin users have the highest level of administrative authority within the OpenSearch environment. This role is typically reserved for select users and should be managed carefully. + +Super admin users have unrestricted access to all settings and data within the cluster, including permissions to: +- Modify Security plugin configurations. +- Access and manage the security index `.opendistro_security`. +- Override any security limitations. + +#### Authentication of the super admin role + +Super admin users are authenticated through certificates, not passwords. The necessary certificates are defined in the `admin_dn` section of the `opensearch.yml` file and must be signed with the same root certificate authority (CA), as shown in the following example: +``` +YAML +plugins.security.authcz.admin_dn: +- CN=kirk,OU=client,O=client,L=test, C=de +``` + +If the super admin certificate is signed by a different CA, then the admin CA must be concatenated with the node's CA in the file defined in `plugins.security.ssl.http.pemtrustedcas_filepath` in `opensearch.yml`. + +For more information, see [Configuring super admin certificates](https://opensearch.org/docs/latest/security/configuration/tls/#configuring-admin-certificates). diff --git a/_security/authentication-backends/jwt.md b/_security/authentication-backends/jwt.md index afcd4c78ee..b6b08388b5 100644 --- a/_security/authentication-backends/jwt.md +++ b/_security/authentication-backends/jwt.md @@ -235,7 +235,7 @@ openid_auth_domain: transport_enabled: true order: 0 http_authenticator: - type: openid + type: openid # use the OpenID Connect domain, since JWT is part of this authentication. challenge: false config: subject_key: preferred_username diff --git a/_security/authentication-backends/ldap.md b/_security/authentication-backends/ldap.md index 188fc5356c..49b01e332b 100755 --- a/_security/authentication-backends/ldap.md +++ b/_security/authentication-backends/ldap.md @@ -19,7 +19,8 @@ In most cases, you want to configure both authentication and authorization. You We provide a fully functional example that can help you understand how to use an LDAP server for both authentication and authorization. -1. Download and unzip [the example zip file]({{site.url}}{{site.baseurl}}/assets/examples/ldap-example.zip). +1. Download and unzip [the example zip file]({{site.url}}{{site.baseurl}}/assets/examples/ldap-example-v2.13.zip). +1. Update the `.env` file with a strong password for `admin` user. 1. At the command line, run `docker-compose up`. 1. Review the files: diff --git a/_security/authentication-backends/openid-connect.md b/_security/authentication-backends/openid-connect.md index 8fc29e262f..8efb66fbb6 100755 --- a/_security/authentication-backends/openid-connect.md +++ b/_security/authentication-backends/openid-connect.md @@ -413,3 +413,21 @@ config: authentication_backend: type: noop ``` + +## Docker example with Keycloak + +The following steps use Docker and [Keycloak IdP](https://www.keycloak.org/) to set up a basic authentication backend: + + +1. Download and unzip the [example OpenID Connect zip file]({{site.url}}{{site.baseurl}}/assets/examples/oidc_example.zip) +2. Update the `.env` file with a strong password for the `admin` user. +3. Substitute the `{IP}` placeholders in `config.yml` and `opensearch_dashboards.yml` with the IP of the local machine. +4. Review the following files: + - `docker-compose.yml` defines a single OpenSearch node, OpenSearch Dashboards, and Keycloak server. + - `new-realm.json` specifies the details of the [realm](https://www.keycloak.org/docs/latest/server_admin/#core-concepts-and-terms). In this example, the realm is named `new`. + - `config.yml` configures `basic_internal_auth_domain` and `oidc_auth_domain`. + - `opensearch_dashboards.yml` should point to Keycloak for authentication. Make sure that the `opensearch_security.openid.connect_url` setting points to the URL of the realm. +5. At the command line, run `docker-compose up`. +6. Access OpenSearch Dashboards at `http://localhost:5601` and log in with username `testuser` and password `testpassword` configured in the `new-realm.json` file. + +After logging in, the `testuser` receives the backend role `admin` from Keycloak, which is mapped to the `all_access` OpenSearch role. These backend roles can be managed using the Keycloak Administrative Console at http://localhost:8080, using username `admin` and password `admin`. diff --git a/_security/configuration/best-practices.md b/_security/configuration/best-practices.md new file mode 100644 index 0000000000..21bbf3940c --- /dev/null +++ b/_security/configuration/best-practices.md @@ -0,0 +1,133 @@ +--- +layout: default +title: Best practices +parent: Configuration +nav_order: 3 +--- + +# Best practices for OpenSearch security + +Setting up security in OpenSearch is crucial for protecting your data. Here are 10 best practices that offer clear steps for keeping your system safe. + +## 1. Use your own PKI to set up SSL/TLS + +Although using your own public key infrastructure (PKI), such as [AWS Certificate Manager](https://docs.aws.amazon.com/crypto/latest/userguide/awspki-service-acm.html), requires more initial effort, a custom PKI provides you with the flexibility needed to set up SSL/TLS in the most secure and performant way. + +### Enable SSL/TLS for node- and REST-layer traffic + +SSL/TLS is enabled by default on the transport layer, which is used for node-to-node communication. SSL/TLS is disabled by default on the REST layer. + +The following setting is required in order to enable encryption on the REST layer: + +``` +plugins.security.ssl.http.enabled: true +``` +{% include copy.html %} + + +For additional configuration options, such as specifying certificate paths, keys, and certificate authority files, refer to [Configuring TLS certificates]({{site.url}}{{site.baseurl}}/security/configuration/tls/). + +### Replace all demo certificates with your own PKI + +The certificates generated when initializing an OpenSearch cluster with `install_demo_configuration.sh` are not suitable for production. These should be replaced with your own certificates. + +You can generate custom certificates in a few different ways. One approach is to use OpenSSL, described in detail at [Generating self-signed certificates]({{site.url}}{{site.baseurl}}/security/configuration/generate-certificates/). Alternatively, there are online tools available that can simplify the certificate creation process, such as the following: + +- [SearchGuard TLS Tool](https://docs.search-guard.com/latest/offline-tls-tool) +- [TLSTool by dylandreimerink](https://github.com/dylandreimerink/tlstool) + +## 2. Prefer client certificate authentication for API authentication + +Client certificate authentication offers a secure alternative to password authentication and is more suitable for machine-to-machine interactions. It also ensures low performance overhead because the authentication occurs on the TLS level. Nearly all client software, such as curl and client libraries, support this authentication method. + +For detailed configuration instructions and additional information about client certificate authentication, see [Enabling client certificate authentication]({{site.url}}{{site.baseurl}}/security/authentication-backends/client-auth/#enabling-client-certificate-authentication). + + +## 3. Prefer SSO using SAML or OpenID for OpenSearch Dashboards authentication + +Implementing single sign-on (SSO) with protocols like SAML or OpenID for OpenSearch Dashboards authentication enhances security by delegating credential management to a dedicated system. + +This approach minimizes direct interaction with passwords in OpenSearch, streamlines authentication processes, and prevents clutter in the internal user database. For more information, go to the [SAML section of the OpenSearch documentation]({{site.url}}{{site.baseurl}}/security/authentication-backends/saml/). + +## 4. Limit the number of roles assigned to a user + +Prioritizing fewer, more intricate user roles over numerous simplistic roles enhances security and simplifies administration. + +Additional best practices for role management include: + +1. Role granularity: Define roles based on specific job functions or access requirements to minimize unnecessary privileges. +2. Regular role review: Regularly review and audit assigned roles to ensure alignment with organizational policies and access needs. + +For more information about roles, go to the documentation on [defining users and roles in OpenSearch]({{site.url}}{{site.baseurl}}/security/access-control/users-roles/). + +## 5. Verify DLS, FLS, and field masking + +If you have configured Document Level Security (DLS), Field Level Security (FLS), or field masking, make sure you double-check your role definitions, especially if a user is mapped to multiple roles. It is highly recommended that you test this by making a GET request to `_plugins/_security/authinfo`. + +The following resources provide detailed examples and additional configurations: + + - [Document-level security]({{site.url}}{{site.baseurl}}/security/access-control/document-level-security/). + - [Field-level security]({{site.url}}{{site.baseurl}}/security/access-control/field-level-security/). + - [Field masking]({{site.url}}{{site.baseurl}}/security/access-control/field-masking/). + +## 6. Use only the essentials for the audit logging configuration + +Extensive audit logging can degrade system performance due to the following: + +- Each logged event adds to the processing load. +- Audit logs can quickly grow in size, consuming significant disk space. + +To ensure optimal performance, disable unnecessary logging and be selective about which logs are used. If not strictly required by compliance regulations, consider turning off audit logging. If audit logging is essential for your cluster, configure it according to your compliance requirements. + +Whenever possible, adhere to these recommendations: + +- Set `audit.log_request_body` to `false`. +- Set `audit.resolve_bulk_requests` to `false`. +- Enable `compliance.write_log_diffs`. +- Minimize entries for `compliance.read_watched_fields`. +- Minimize entries for `compliance.write_watched_indices`. + +## 7. Consider disabling the private tenant + +In many cases, the use of private tenants is unnecessary, although this feature is enabled by default. As a result, every OpenSearch Dashboards user is provided with their own private tenant and a corresponding new index in which to save objects. This can lead to a large number of unnecessary indexes. Evaluate whether private tenants are needed in your cluster. If private tenants are not needed, disable the feature by adding the following configuration to the `config.yml` file: + +```yaml +config: + dynamic: + kibana: + multitenancy_enabled: true + private_tenant_enabled: false +``` +{% include copy.html %} + +## 8. Manage the configuration using `securityadmin.sh` + +Use `securityadmin.sh` to manage the configuration of your clusters. `securityadmin.sh` is a command-line tool provided by OpenSearch for managing security configurations. It allows administrators to efficiently manage security settings, including roles, role mappings, and other security-related configurations within an OpenSearch cluster. + +Using `securityadmin.sh` provides the following benefits: + +1. Consistency: By using `securityadmin.sh`, administrators can ensure consistency across security configurations within a cluster. This helps to maintain a standardized and secure environment. +2. Automation: `securityadmin.sh` enables automation of security configuration tasks, making it easier to deploy and manage security settings across multiple nodes or clusters. +3. Version control: Security configurations managed through `securityadmin.sh` can be version controlled using standard version control systems like Git. This facilitates tracking changes, auditing, and reverting to previous configurations. + +You can prevent configuration overrides by first creating a backup of the current configuration created using the OpenSearch Dashboards UI or the OpenSearch API by running the `securityadmin.sh` tool with the `-backup` option. This ensures that all configurations are captured before uploading the modified configuration with `securityadmin.sh`. + +For more detailed information about using `securityadmin.sh` and managing OpenSearch security configurations, refer to the following resources: +- [Applying changes to configuration files]({{site.url}}{{site.baseurl}}/security/configuration/security-admin/) +- [Modifying YAML files]({{site.url}}{{site.baseurl}}/security/configuration/yaml/) + +## 9. Replace all default passwords + +When initializing OpenSearch with the demo configuration, many default passwords are provided for internal users in `internal_users.yml`, such as `admin`, `kibanaserver`, and `logstash`. + +You should change the passwords for these users to strong, complex passwords either at startup or as soon as possible once the cluster is running. Creating password configurations is a straightforward procedure, especially when using the scripts bundled with OpenSearch, like `hash.sh` or `hash.bat`, located in the `plugin/OpenSearch security/tools` directory. + +The `kibanaserver` user is a crucial component that allows OpenSearch Dashboards to communicate with the OpenSearch cluster. By default, this user is preconfigured with a default password in the demo configuration. This should be replaced with a strong, unique password in the OpenSearch configuration, and the `opensearch_dashboards.yml` file should be updated to reflect this change. + + +## 10. Getting help + +If you need additional help, you can do the following: + +- Create an issue on GitHub at [OpenSearch-project/security](https://github.com/opensearch-project/security/security) or [OpenSearch-project/OpenSearch](https://github.com/opensearch-project/OpenSearch/security). +- Ask a question on the [OpenSearch forum](https://forum.opensearch.org/tag/cve). diff --git a/_security/configuration/configuration.md b/_security/configuration/configuration.md index d4f6a47cde..2a038b7fb9 100755 --- a/_security/configuration/configuration.md +++ b/_security/configuration/configuration.md @@ -11,7 +11,7 @@ redirect_from: One of the first steps when setting up the Security plugin is deciding which authentication backend to use. The role played by the backend in authentication is covered in [steps 2 and 3 of the authentication flow]({{site.url}}{{site.baseurl}}/security/authentication-backends/authc-index/#authentication-flow). The plugin has an internal user database, but many people prefer to use an existing authentication backend, such as an LDAP server, or some combination of the two. -The primary file used to configure an authentication and authorization backend is `config/opensearch-security/config.yml`. This file defines how the Security plugin retrieves user credentials, how it verifies the credentials, and how it fetches additional roles when the backend selected for authentication and authorization supports this feature. This topic provides a basic overview of the configuration file and its requirements for setting up security. For information about configuring a specific backend, see [Authentication backends]({{site.url}}{{site.baseurl}}/security/authentication-backends/authc-index/). +The primary file used to configure the authentication and authorization backend is `/usr/share/opensearch/config/opensearch-security/config.yml`. This file defines how the Security plugin retrieves user credentials, how the plugin verifies the credentials, and how the plugin fetches additional roles when the backend selected for authentication and authorization supports this feature. This topic provides a basic overview of the configuration file and its requirements for setting up security. For information about configuring a specific backend, see [Authentication backends]({{site.url}}{{site.baseurl}}/security/authentication-backends/authc-index/). The `config.yml` file includes three main parts: diff --git a/_security/configuration/demo-configuration.md b/_security/configuration/demo-configuration.md index 22640b001c..33794b0d67 100644 --- a/_security/configuration/demo-configuration.md +++ b/_security/configuration/demo-configuration.md @@ -27,14 +27,15 @@ The demo configuration is automatically called as part of the setup for each sup Use the following steps to set up the Security plugin using Docker: 1. Download [docker-compose.yml](https://opensearch.org/downloads.html). -2. In the `docker-compose.yml` file, set `DISABLE_SECURITY_PLUGIN` to `false`. -3. Run the following command: +2. Run the following command: ```bash docker-compose up ``` {% include copy.html %} +If you want to disable the Security plugin when using Docker, set the `DISABLE_SECURITY_PLUGIN` environment variable to `true` in the `docker-compose.yml` file. Disabling the Security plugin is not recommended. For more information, see the [Docker image release README](https://github.com/opensearch-project/opensearch-build/tree/main/docker/release#disable-security-plugin-security-dashboards-plugin-security-demo-configurations-and-related-configurations) in GitHub. + ### Setting up a custom admin password **Note**: For OpenSearch versions 2.12 and later, you must set the initial admin password before installation. To customize the admin password, you can take the following steps: diff --git a/_security/configuration/tls.md b/_security/configuration/tls.md index 3d8c23a391..d06b16a47e 100755 --- a/_security/configuration/tls.md +++ b/_security/configuration/tls.md @@ -128,14 +128,16 @@ If your node certificates have an Object ID (OID) identifier in the SAN section, ## Configuring admin certificates -Admin certificates are regular client certificates that have elevated rights to perform administrative tasks. You need an admin certificate to change the Security plugin configuration using [`plugins/opensearch-security/tools/securityadmin.sh`]({{site.url}}{{site.baseurl}}/security/configuration/security-admin/) or the REST API. Admin certificates are configured in `opensearch.yml` by stating their DN(s): +Super admin certificates are regular client certificates that have elevated rights to perform administrative security tasks. You need an admin certificate to change the Security plugin configuration using [`plugins/opensearch-security/tools/securityadmin.sh`]({{site.url}}{{site.baseurl}}/security/configuration/security-admin/) or the REST API. Super admin certificates are configured in `opensearch.yml` by stating their DN(s): ```yml plugins.security.authcz.admin_dn: - CN=admin,OU=SSL,O=Test,L=Test,C=DE ``` -For security reasons, you can't use wildcards or regular expressions here. +For security reasons, you cannot use wildcards or regular expressions as values for the `admin_dn` setting. + +For more information about admin and super admin user roles, see [Admin and super admin roles](https://opensearch.org/docs/latest/security/access-control/users-roles/#admin-and-super-admin-roles) and [Configuring super admin certificates](https://opensearch.org/docs/latest/security/configuration/tls/#configuring-admin-certificates). ## (Advanced) OpenSSL @@ -237,7 +239,6 @@ plugins.security.ssl.http.enabled_protocols: - "TLSv1.2" ``` - ## (Advanced) Disabling client initiated renegotiation for Java 8 Set `-Djdk.tls.rejectClientInitiatedRenegotiation=true` to disable secure client initiated renegotiation, which is enabled by default. This can be set via `OPENSEARCH_JAVA_OPTS` in `config/jvm.options`. diff --git a/_security/index.md b/_security/index.md index b2fd193427..d4af6f0337 100755 --- a/_security/index.md +++ b/_security/index.md @@ -75,5 +75,8 @@ To learn more, see [Cross-cluster search]({{site.url}}{{site.baseurl}}/security/ ## Next steps -To get started, see the configuration overview in the [Security configuration]({{site.url}}{{site.baseurl}}/security/configuration/index/) section, which provides the basic steps for setting up security in your OpenSearch implementation and includes links to information about customizing security for your business needs. +The [Best practices for OpenSearch security]({{site.url}}{{site.baseurl}}/security/configuration/best-practices/) guide covers 10 things to consider when getting started with OpenSearch security. + +The [Security configuration]({{site.url}}{{site.baseurl}}/security/configuration/index/) overview provides the basic steps for setting up security in your OpenSearch implementation and includes links to information about customizing security for your business needs. + diff --git a/_security/multi-tenancy/tenant-index.md b/_security/multi-tenancy/tenant-index.md index d4e13ad193..0ed9123ce0 100644 --- a/_security/multi-tenancy/tenant-index.md +++ b/_security/multi-tenancy/tenant-index.md @@ -6,6 +6,7 @@ has_children: true has_toc: false redirect_from: - /security/multi-tenancy/ + - /security-plugin/access-control/multi-tenancy/ --- # OpenSearch Dashboards multi-tenancy diff --git a/_tools/grafana.md b/_tools/grafana.md index 16a899d82e..8f38054303 100644 --- a/_tools/grafana.md +++ b/_tools/grafana.md @@ -3,6 +3,8 @@ layout: default title: Grafana nav_order: 200 has_children: false +redirect_from: + - /clients/grafana/ --- # Grafana support diff --git a/_tools/k8s-operator.md b/_tools/k8s-operator.md index 403aabd631..7ee1c1adee 100644 --- a/_tools/k8s-operator.md +++ b/_tools/k8s-operator.md @@ -3,6 +3,8 @@ layout: default title: OpenSearch Kubernetes Operator nav_order: 80 has_children: false +redirect_from: + - /clients/k8s-operator/ --- The OpenSearch Kubernetes Operator is an open-source kubernetes operator that helps automate the deployment and provisioning of OpenSearch and OpenSearch Dashboards in a containerized environment. The operator can manage multiple OpenSearch clusters that can be scaled up and down depending on your needs. diff --git a/_tools/logstash/common-filters.md b/_tools/logstash/common-filters.md index 4cfc2b6703..909461261d 100644 --- a/_tools/logstash/common-filters.md +++ b/_tools/logstash/common-filters.md @@ -73,7 +73,7 @@ Logstash supports a few common options for all filter plugins: Option | Description :--- | :--- `add_field` | Adds one or more fields to the event. -`remove_field` | Removes one or more events from the field. +`remove_field` | Removes one or more fields from the event. `add_tag` | Adds one or more tags to the event. You can use tags to perform conditional processing on events depending on which tags they contain. `remove_tag` | Removes one or more tags from the event. diff --git a/_tools/logstash/read-from-opensearch.md b/_tools/logstash/read-from-opensearch.md index 84d44951e5..53024c233b 100644 --- a/_tools/logstash/read-from-opensearch.md +++ b/_tools/logstash/read-from-opensearch.md @@ -4,7 +4,8 @@ title: Read from OpenSearch parent: Logstash nav_order: 220 redirect_from: - - /clients/logstash/ship-to-opensearch/ + - /clients/logstash/read-from-opensearch/ + - /clients/logstash/ship-to-opensearch/ --- # Read from OpenSearch diff --git a/_troubleshoot/security-admin.md b/_troubleshoot/security-admin.md index 5f9b5709ca..f36f1e3b0b 100644 --- a/_troubleshoot/security-admin.md +++ b/_troubleshoot/security-admin.md @@ -92,7 +92,7 @@ Connected as CN=node-0.example.com,OU=SSL,O=Test,L=Test,C=DE ERR: CN=node-0.example.com,OU=SSL,O=Test,L=Test,C=DE is not an admin user ``` -You must use an admin certificate when executing the script. To learn more, see [Configuring admin certificates]({{site.url}}{{site.baseurl}}/security/configuration/tls/#configuring-admin-certificates). +You must use an admin certificate when executing the script. To learn more, see [Configuring super admin certificates](https://opensearch.org/docs/latest/security/configuration/tls/#configuring-admin-certificates). ## Use the diagnose option diff --git a/_tuning-your-cluster/availability-and-recovery/remote-store/migrating-to-remote.md b/_tuning-your-cluster/availability-and-recovery/remote-store/migrating-to-remote.md index 65ae48735b..d97150812e 100644 --- a/_tuning-your-cluster/availability-and-recovery/remote-store/migrating-to-remote.md +++ b/_tuning-your-cluster/availability-and-recovery/remote-store/migrating-to-remote.md @@ -8,10 +8,7 @@ grand_parent: Availability and recovery # Migrating to remote-backed storage -This is an experimental feature and is not recommended for use in a production environment. For updates on the progress of the feature or if you want to leave feedback, see the associated [GitHub issue](https://github.com/opensearch-project/OpenSearch/issues/7986). -{: .warning} - -Introduced 2.14 +Introduced 2.15 {: .label .label-purple } Remote-backed storage offers a new way to protect against data loss by automatically creating backups of all index transactions and sending them to remote storage. To use this feature, [segment replication]({{site.url}}{{site.baseurl}}/opensearch/segment-replication/) must be enabled. @@ -24,9 +21,9 @@ Rolling upgrades, sometimes referred to as *node replacement upgrades*, can be p Review [Upgrading OpenSearch]({{site.url}}{{site.baseurl}}/upgrade-opensearch/index/) for recommendations about backing up your configuration files and creating a snapshot of the cluster state and indexes before you make any changes to your OpenSearch cluster. -Before migrating to remote-backed storage, upgrade to OpenSearch 2.14. +Before migrating to remote-backed storage, upgrade to OpenSearch 2.15 or later. -As of OpenSearch 2.14, OpenSearch nodes cannot be migrated back to document replication. If you need to revert the migration, then you will need to perform a fresh installation of OpenSearch and restore the cluster from a snapshot. Take a snapshot and store it in a remote repository before beginning the upgrade procedure. +Before upgrading to OpenSearch 2.15, take a cluster snapshot and store it remotely. OpenSearch 2.15 nodes cannot revert to document replication. If a migration needs to be undone, perform a fresh OpenSearch installation and restore from the remote snapshot. Storing the snapshot remotely allows you to retrieve and restore it if issues arise during migration. {: .important} ## Performing the upgrade @@ -105,14 +102,14 @@ As of OpenSearch 2.14, OpenSearch nodes cannot be migrated back to document repl } ``` -1. Set the `remote_store.compatibility_mode` setting to `mixed` to allow remote-backed storage nodes to join the cluster. Then set `migration.direction` to `remote_store`, which allocates new indexes to remote-backed data nodes. The following example updates the aforementioned setting using the Cluster Settings API: +1. Set the `cluster.remote_store.compatibility_mode` setting to `mixed` to allow remote-backed storage nodes to join the cluster. Then set `cluster.migration.direction` to `remote_store`, which allocates new indexes to remote-backed data nodes. The following example updates the aforementioned setting using the Cluster Settings API: ```json PUT "/_cluster/settings?pretty" { "persistent": { - "remote_store.compatibility_mode": "mixed", - "migration.direction" : "remote_store" + "cluster.remote_store.compatibility_mode": "mixed", + "cluster.migration.direction" : "remote_store" } } ``` @@ -121,13 +118,15 @@ As of OpenSearch 2.14, OpenSearch nodes cannot be migrated back to document repl ```json { "acknowledged" : true, - "persistent" : { - "remote_store" : { - "compatibility_mode" : "mixed", - "migration.direction" : "remote_store" + "persistent" : { + "cluster" : { + "remote_store" : { + "compatibility_mode" : "mixed", + "migration.direction" : "remote_store" + } }, "transient" : { } - } + } } ``` @@ -233,8 +232,8 @@ As of OpenSearch 2.14, OpenSearch nodes cannot be migrated back to document repl PUT "/_cluster/settings?pretty" { "persistent": { - "remote_store.compatibility_mode": strict, - "migration.direction" : none + "cluster.remote_store.compatibility_mode": null, + "cluster.migration.direction" : null } } ``` @@ -243,7 +242,10 @@ As of OpenSearch 2.14, OpenSearch nodes cannot be migrated back to document repl ```json { "acknowledged" : true, - "persistent" : { strict }, + "persistent" : { + "cluster.remote_store.compatibility_mode": null, + "cluster.migration.direction" : null + }, "transient" : { } } ``` @@ -255,8 +257,8 @@ The migration to the remote store is now complete. Use the following cluster settings to enable migration to a remote-backed cluster. -| Field | Data type | Description | -| :--- |:--- |:---| -| `remote_store.compatibility_mode` | String | When set to `strict`, only allows the creation of either non-remote or remote nodes, depending upon the initial cluster type. When set to `mixed`, allows both remote and non-remote nodes to join the cluster. Default is `strict`. | -| `migration.direction` | String | Creates new shards only on remote-backed storage nodes. Default is `None`. | +| Field | Data type | Description | +|:------------------------------------------|:--- |:---| +| `cluster.remote_store.compatibility_mode` | String | When set to `strict`, only allows the creation of either non-remote or remote nodes, depending on the initial cluster type. When set to `mixed`, allows both remote and non-remote nodes to join the cluster. Default is `strict`. | +| `cluster.migration.direction` | String | Creates new shards only on remote-backed storage nodes. Default is `None`. | diff --git a/_tuning-your-cluster/availability-and-recovery/remote-store/remote-cluster-state.md b/_tuning-your-cluster/availability-and-recovery/remote-store/remote-cluster-state.md index 7cc533fe76..d967aca914 100644 --- a/_tuning-your-cluster/availability-and-recovery/remote-store/remote-cluster-state.md +++ b/_tuning-your-cluster/availability-and-recovery/remote-store/remote-cluster-state.md @@ -54,12 +54,43 @@ In addition to the mandatory static settings, you can configure the following dy Setting | Default | Description :--- | :--- | :--- -`cluster.remote_store.state.index_metadata.upload_timeout` | 20s | The amount of time to wait for index metadata upload to complete. Note that index metadata for separate indexes is uploaded in parallel. -`cluster.remote_store.state.global_metadata.upload_timeout` | 20s | The amount of time to wait for global metadata upload to complete. Global metadata contains globally applicable metadata, such as templates, cluster settings, data stream metadata, and repository metadata. -`cluster.remote_store.state.metadata_manifest.upload_timeout` | 20s | The amount of time to wait for the manifest file upload to complete. The manifest file contains the details of each of the files uploaded for a single cluster state, both index metadata files and global metadata files. +`cluster.remote_store.state.index_metadata.upload_timeout` | 20s | Deprecated. Use `cluster.remote_store.state.global_metadata.upload_timeout` instead. +`cluster.remote_store.state.global_metadata.upload_timeout` | 20s | The amount of time to wait for the cluster state upload to complete. +`cluster.remote_store.state.metadata_manifest.upload_timeout` | 20s | The amount of time to wait for the manifest file upload to complete. The manifest file contains the details of each of the files uploaded for a single cluster state, both index metadata files and global metadata files. +`cluster.remote_store.state.cleanup_interval` | 300s | The interval at which the asynchronous remote state clean-up task runs. This task deletes any old remote state files. ## Limitations The remote cluster state functionality has the following limitations: - Unsafe bootstrap scripts cannot be run when the remote cluster state is enabled. When a majority of cluster-manager nodes are lost and the cluster goes down, the user needs to replace any remaining cluster manager nodes and reseed the nodes in order to bootstrap a new cluster. + +## Remote cluster state publication + + +The cluster manager node processes updates to the cluster state. It then publishes the updated cluster state through the local transport layer to all of the follower nodes. With the `remote_store.publication` feature enabled, the cluster state is backed up to the remote store during every state update. The follower nodes can then fetch the state from the remote store directly, which reduces the overhead on the cluster manager node for publication. + +To enable the feature flag for the `remote_store.publication` feature, follow the steps in the [experimental feature flag documentation]({{site.url}}{{site.baseurl}}/install-and-configure/configuring-opensearch/experimental/). + +Enabling the setting does not change the publication flow, and follower nodes will not send acknowledgements back to the cluster manager node +until they download the updated cluster state from the remote store. + +You must enable the remote cluster state feature in order for remote publication to work. To modify the remote publication behavior, the following routing table repository settings can be used, which contain the shard allocation details for each index in the remote cluster state: + +```yml +# Remote routing table repository settings +node.attr.remote_store.routing_table.repository: my-remote-routing-table-repo +node.attr.remote_store.repository.my-remote-routing-table-repo.type: s3 +node.attr.remote_store.repository.my-remote-routing-table-repo.settings.bucket: +node.attr.remote_store.repository.my-remote-routing-table-repo.settings.region: +``` + +You do not have to use different remote store repositories for state and routing because both state and routing can use the same repository settings. + +To configure remote publication, use the following cluster settings. + +Setting | Default | Description +:--- | :--- | :--- +`cluster.remote_store.state.read_timeout` | 20s | The amount of time to wait for remote state download to complete on the follower node. +`cluster.remote_store.routing_table.path_type` | HASHED_PREFIX | The path type to be used for creating an index routing path in the blob store. Valid values are `FIXED`, `HASHED_PREFIX`, and `HASHED_INFIX`. +`cluster.remote_store.routing_table.path_hash_algo` | FNV_1A_BASE64 | The algorithm to be used for constructing the prefix or infix of the blob store path. This setting is applied if `cluster.remote_store.routing_table.path_type` is `hashed_prefix` or `hashed_infix`. Valid algorithm values are `FNV_1A_BASE64` and `FNV_1A_COMPOSITE_1`. diff --git a/_tuning-your-cluster/availability-and-recovery/snapshots/snapshot-restore.md b/_tuning-your-cluster/availability-and-recovery/snapshots/snapshot-restore.md index 91d0baca92..f35115c95f 100644 --- a/_tuning-your-cluster/availability-and-recovery/snapshots/snapshot-restore.md +++ b/_tuning-your-cluster/availability-and-recovery/snapshots/snapshot-restore.md @@ -207,7 +207,7 @@ You will most likely not need to specify any parameters except for `location`. F You will most likely not need to specify any parameters except for `bucket` and `base_path`. For allowed request parameters, see [Register or update snapshot repository API](https://opensearch.org/docs/latest/api-reference/snapshots/create-repository/). -### Registering an Azure storage account +### Registering a Microsoft Azure storage account using Helm Use the following steps to register a snapshot repository backed by an Azure storage account for an OpenSearch cluster deployed using Helm. @@ -296,6 +296,56 @@ Use the following steps to register a snapshot repository backed by an Azure sto } ``` +### Set up Microsoft Azure Blob Storage + +To use Azure Blob Storage as a snapshot repository, follow these steps: +1. Install the `repository-azure` plugin on all nodes with the following command: + + ```bash + ./bin/opensearch-plugin install repository-azure + ``` + +1. After the `repository-azure` plugin is installed, define your Azure Blob Storage settings before initializing the node. Start by defining your Azure Storage account name using the following secure setting: + + ```bash + ./bin/opensearch-keystore add azure.client.default.account + ``` + +Choose one of the following options for setting up your Azure Blob Storage authentication credentials. + +#### Using an Azure Storage account key + +Use the following setting to specify your Azure Storage account key: + +```bash +./bin/opensearch-keystore add azure.client.default.key +``` + +#### Shared access signature + +Use the following setting when accessing Azure with a shared access signature (SAS): + +```bash +./bin/opensearch-keystore add azure.client.default.sas_token +``` + +#### Azure token credential + +Starting in OpenSearch 2.15, you have the option to configure a token credential authentication flow in `opensearch.yml`. This method is distinct from connection string authentication, which requires a SAS or an account key. + +If you choose to use token credential authentication, you will need to choose a token credential type. Although Azure offers multiple token credential types, as of OpenSearch version 2.15, only [managed identity](https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/overview) is supported. + +To use managed identity, add your token credential type to `opensearch.yml` using either the `managed` or `managed_identity` value. This indicates that managed identity is being used to perform token credential authentication: + +```yml +azure.client.default.token_credential_type: "managed_identity" +``` + +Note the following when using Azure token credentials: + +- Token credential support is disabled in `opensearch.yml` by default. +- A token credential takes precedence over an Azure Storage account key or a SAS when multiple options are configured. + ## Take snapshots You specify two pieces of information when you create a snapshot: @@ -447,7 +497,9 @@ We recommend ceasing write requests to a cluster before restoring from a snapsho 1. A write request to the now-deleted alias creates a new index with the same name as the alias. 1. The alias from the snapshot fails to restore due to a naming conflict with the new index. -Snapshots are only forward-compatible by one major version. If you have an old snapshot, you can sometimes restore it into an intermediate cluster, reindex all indexes, take a new snapshot, and repeat until you arrive at your desired version, but you might find it easier to just manually index your data in the new cluster. +Snapshots are only forward compatible by one major version. Snapshots taken by earlier OpenSearch versions can continue to be restored by the version of OpenSearch that originally took the snapshot, even after a version upgrade. For example, a snapshot taken by OpenSearch 2.11 or earlier can continue to be restored by a 2.11 cluster even after upgrading to 2.12. + +If you have an old snapshot taken from an earlier major OpenSearch version, you can restore it to an intermediate cluster one major version newer than the snapshot's version, reindex all indexes, take a new snapshot, and repeat until you arrive at your desired major version, but you may find it easier to manually index your data in the new cluster. ## Security considerations diff --git a/assets/examples/ldap-example-v2.13.zip b/assets/examples/ldap-example-v2.13.zip new file mode 100644 index 0000000000..9531848ea8 Binary files /dev/null and b/assets/examples/ldap-example-v2.13.zip differ diff --git a/assets/examples/ldap-example-v2.zip b/assets/examples/ldap-example-v2.zip deleted file mode 100644 index a3d09862d0..0000000000 Binary files a/assets/examples/ldap-example-v2.zip and /dev/null differ diff --git a/assets/examples/ldap-example.zip b/assets/examples/ldap-example.zip deleted file mode 100644 index acecc3e5c2..0000000000 Binary files a/assets/examples/ldap-example.zip and /dev/null differ diff --git a/assets/examples/oidc_example.zip b/assets/examples/oidc_example.zip new file mode 100644 index 0000000000..e2d3cbf951 Binary files /dev/null and b/assets/examples/oidc_example.zip differ diff --git a/images/alerting/cross-cluster-cluster-metrics-monitors.png b/images/alerting/cross-cluster-cluster-metrics-monitors.png index 16d63f5980..4d0ca53116 100644 Binary files a/images/alerting/cross-cluster-cluster-metrics-monitors.png and b/images/alerting/cross-cluster-cluster-metrics-monitors.png differ diff --git a/images/alerting/cross-cluster-per-query-per-bucket-monitors.png b/images/alerting/cross-cluster-per-query-per-bucket-monitors.png index 325535885c..dfbfb171fd 100644 Binary files a/images/alerting/cross-cluster-per-query-per-bucket-monitors.png and b/images/alerting/cross-cluster-per-query-per-bucket-monitors.png differ diff --git a/images/benchmark/OSB-workflow.png b/images/benchmark/OSB-workflow.png deleted file mode 100644 index cedbf577a1..0000000000 Binary files a/images/benchmark/OSB-workflow.png and /dev/null differ diff --git a/images/benchmark/osb-workflow.jpg b/images/benchmark/osb-workflow.jpg new file mode 100644 index 0000000000..28da18274a Binary files /dev/null and b/images/benchmark/osb-workflow.jpg differ diff --git a/images/dashboards/drag-drop-generated-viz.png b/images/dashboards/drag-drop-generated-viz.png new file mode 100644 index 0000000000..b1cdea95d9 Binary files /dev/null and b/images/dashboards/drag-drop-generated-viz.png differ diff --git a/images/dashboards/integrations-assets.png b/images/dashboards/integrations-assets.png new file mode 100644 index 0000000000..90700988ff Binary files /dev/null and b/images/dashboards/integrations-assets.png differ diff --git a/images/dashboards/mds_feature_anywhere_create_alerting.gif b/images/dashboards/mds_feature_anywhere_create_alerting.gif new file mode 100644 index 0000000000..712cace8bf Binary files /dev/null and b/images/dashboards/mds_feature_anywhere_create_alerting.gif differ diff --git a/images/dashboards/mds_feature_anywhere_view_alerting.gif b/images/dashboards/mds_feature_anywhere_view_alerting.gif new file mode 100644 index 0000000000..ff840cfad4 Binary files /dev/null and b/images/dashboards/mds_feature_anywhere_view_alerting.gif differ diff --git a/images/dashboards/mds_monitor_view.gif b/images/dashboards/mds_monitor_view.gif new file mode 100644 index 0000000000..9ada1147f5 Binary files /dev/null and b/images/dashboards/mds_monitor_view.gif differ diff --git a/images/dashboards/mds_sa_detection_rules_create.gif b/images/dashboards/mds_sa_detection_rules_create.gif new file mode 100644 index 0000000000..50fc77b8d6 Binary files /dev/null and b/images/dashboards/mds_sa_detection_rules_create.gif differ diff --git a/images/dashboards/mds_sa_detection_rules_view.gif b/images/dashboards/mds_sa_detection_rules_view.gif new file mode 100644 index 0000000000..31508f10de Binary files /dev/null and b/images/dashboards/mds_sa_detection_rules_view.gif differ diff --git a/images/dashboards/os-assistant-chat.png b/images/dashboards/os-assistant-chat.png new file mode 100644 index 0000000000..40a319394f Binary files /dev/null and b/images/dashboards/os-assistant-chat.png differ diff --git a/images/dashboards/os-assistant-icon.png b/images/dashboards/os-assistant-icon.png new file mode 100644 index 0000000000..2a27c6099f Binary files /dev/null and b/images/dashboards/os-assistant-icon.png differ diff --git a/images/dashboards/vis-builder-1.png b/images/dashboards/vis-builder-1.png index a139daec09..aa159a2987 100644 Binary files a/images/dashboards/vis-builder-1.png and b/images/dashboards/vis-builder-1.png differ diff --git a/images/dashboards/vis-builder-2.png b/images/dashboards/vis-builder-2.png index 748c4755cb..d7b0c26d6e 100644 Binary files a/images/dashboards/vis-builder-2.png and b/images/dashboards/vis-builder-2.png differ diff --git a/images/drag-drop-generated-viz.png b/images/drag-drop-generated-viz.png deleted file mode 100644 index b1a9724eb8..0000000000 Binary files a/images/drag-drop-generated-viz.png and /dev/null differ diff --git a/images/integrations/cloud-integrations-filter.png b/images/integrations/cloud-integrations-filter.png new file mode 100644 index 0000000000..76da993144 Binary files /dev/null and b/images/integrations/cloud-integrations-filter.png differ diff --git a/images/integrations/empty-installed-integrations.png b/images/integrations/empty-installed-integrations.png new file mode 100644 index 0000000000..4bcd6e2063 Binary files /dev/null and b/images/integrations/empty-installed-integrations.png differ diff --git a/images/integrations/import-saved-objects.png b/images/integrations/import-saved-objects.png new file mode 100644 index 0000000000..af13da47c0 Binary files /dev/null and b/images/integrations/import-saved-objects.png differ diff --git a/images/integrations/integration-catalog-release-page.png b/images/integrations/integration-catalog-release-page.png new file mode 100644 index 0000000000..30b033e472 Binary files /dev/null and b/images/integrations/integration-catalog-release-page.png differ diff --git a/images/integrations/integration-import-file.png b/images/integrations/integration-import-file.png new file mode 100644 index 0000000000..867f3356b4 Binary files /dev/null and b/images/integrations/integration-import-file.png differ diff --git a/images/integrations/integrations-observability-catalog.png b/images/integrations/integrations-observability-catalog.png new file mode 100644 index 0000000000..43cdaa8684 Binary files /dev/null and b/images/integrations/integrations-observability-catalog.png differ diff --git a/images/integrations/nginx-installed-integration-assets.png b/images/integrations/nginx-installed-integration-assets.png new file mode 100644 index 0000000000..0255472619 Binary files /dev/null and b/images/integrations/nginx-installed-integration-assets.png differ diff --git a/images/integrations/nginx-integration-dashboard.png b/images/integrations/nginx-integration-dashboard.png new file mode 100644 index 0000000000..6f99f4fc0c Binary files /dev/null and b/images/integrations/nginx-integration-dashboard.png differ diff --git a/images/integrations/nginx-integration.gif b/images/integrations/nginx-integration.gif deleted file mode 100644 index fb8df1d2bf..0000000000 Binary files a/images/integrations/nginx-integration.gif and /dev/null differ diff --git a/images/integrations/nginx-integration.png b/images/integrations/nginx-integration.png new file mode 100644 index 0000000000..c23fd453fb Binary files /dev/null and b/images/integrations/nginx-integration.png differ diff --git a/images/integrations/select-uploaded-integration.png b/images/integrations/select-uploaded-integration.png new file mode 100644 index 0000000000..950d168a68 Binary files /dev/null and b/images/integrations/select-uploaded-integration.png differ diff --git a/images/metrics/otel-metrics-remote-cluster-selection.png b/images/metrics/otel-metrics-remote-cluster-selection.png new file mode 100644 index 0000000000..116b8a166a Binary files /dev/null and b/images/metrics/otel-metrics-remote-cluster-selection.png differ diff --git a/images/metrics/otel-metrics.png b/images/metrics/otel-metrics.png new file mode 100644 index 0000000000..cd90952781 Binary files /dev/null and b/images/metrics/otel-metrics.png differ diff --git a/images/metrics/prom-metrics.png b/images/metrics/prom-metrics.png new file mode 100644 index 0000000000..6a34ee7fde Binary files /dev/null and b/images/metrics/prom-metrics.png differ diff --git a/images/metrics/remote-cluster-selection.png b/images/metrics/remote-cluster-selection.png new file mode 100644 index 0000000000..eaeae1d534 Binary files /dev/null and b/images/metrics/remote-cluster-selection.png differ diff --git a/images/trace-analytics/service-details-tooltip.png b/images/trace-analytics/service-details-tooltip.png new file mode 100644 index 0000000000..22e172be41 Binary files /dev/null and b/images/trace-analytics/service-details-tooltip.png differ diff --git a/images/trace-analytics/service-throughput-tooltip.png b/images/trace-analytics/service-throughput-tooltip.png new file mode 100644 index 0000000000..ba33ccdd57 Binary files /dev/null and b/images/trace-analytics/service-throughput-tooltip.png differ diff --git a/images/trace-analytics/services-filter-selection.png b/images/trace-analytics/services-filter-selection.png new file mode 100644 index 0000000000..8eba634117 Binary files /dev/null and b/images/trace-analytics/services-filter-selection.png differ diff --git a/images/trace-analytics/services-table.png b/images/trace-analytics/services-table.png new file mode 100644 index 0000000000..583ae70eb4 Binary files /dev/null and b/images/trace-analytics/services-table.png differ diff --git a/images/trace-analytics/single-service-RED-metrics.png b/images/trace-analytics/single-service-RED-metrics.png new file mode 100644 index 0000000000..e14ebc1da9 Binary files /dev/null and b/images/trace-analytics/single-service-RED-metrics.png differ diff --git a/images/trace-analytics/single-service-correlation-dialog.png b/images/trace-analytics/single-service-correlation-dialog.png new file mode 100644 index 0000000000..0f1cbd83ea Binary files /dev/null and b/images/trace-analytics/single-service-correlation-dialog.png differ diff --git a/images/trace-analytics/single-service-fly-out.png b/images/trace-analytics/single-service-fly-out.png new file mode 100644 index 0000000000..03e7b6a691 Binary files /dev/null and b/images/trace-analytics/single-service-fly-out.png differ diff --git a/images/trace-analytics/span-details-fly-out.png b/images/trace-analytics/span-details-fly-out.png new file mode 100644 index 0000000000..685147e380 Binary files /dev/null and b/images/trace-analytics/span-details-fly-out.png differ diff --git a/images/trace-analytics/trace-group-RED-metrics.png b/images/trace-analytics/trace-group-RED-metrics.png new file mode 100644 index 0000000000..d7d5143e68 Binary files /dev/null and b/images/trace-analytics/trace-group-RED-metrics.png differ diff --git a/release-notes/opensearch-documentation-release-notes-2.15.0.md b/release-notes/opensearch-documentation-release-notes-2.15.0.md new file mode 100644 index 0000000000..5f7ab9b049 --- /dev/null +++ b/release-notes/opensearch-documentation-release-notes-2.15.0.md @@ -0,0 +1,42 @@ +# OpenSearch Documentation Website 2.15.0 Release Notes + +The OpenSearch 2.15.0 documentation includes the following additions and updates. + +## New documentation for 2.15.0 + +- Alerts in correlations feature documentation [#7410](https://github.com/opensearch-project/documentation-website/pull/7410) +- Add documentations for batch ingestion feature [#7408](https://github.com/opensearch-project/documentation-website/pull/7408) +- Changed VisBuilder status from experimental to GA [#7405](https://github.com/opensearch-project/documentation-website/pull/7405) +- Add documentation for innerHit on knn nested field [#7404](https://github.com/opensearch-project/documentation-website/pull/7404) +- AD Enhancements in Version 2.15 [#7388](https://github.com/opensearch-project/documentation-website/pull/7388) +- Add connector tool [#7384](https://github.com/opensearch-project/documentation-website/pull/7384) +- Add remote guardrails model support [#7377](https://github.com/opensearch-project/documentation-website/pull/7377) +- Update documentation of ml inference processors to support for local models [#7368](https://github.com/opensearch-project/documentation-website/pull/7368) +- Trace analytics update [#7362](https://github.com/opensearch-project/documentation-website/pull/7362) +- Add doc for alerting comments [#7360](https://github.com/opensearch-project/documentation-website/pull/7360) +- Add documentation related to removal of source and recovery source in k-NN performance tuning section [#7359](https://github.com/opensearch-project/documentation-website/pull/7359) +- Added documentation for new default workflow templates [#7346](https://github.com/opensearch-project/documentation-website/pull/7346) +- Mark docrep to remote migration as GA and modify settings names [#7342](https://github.com/opensearch-project/documentation-website/pull/7342) +- Add documentation for the new setting of cardinality aggregation dynamic pruning [#7341](https://github.com/opensearch-project/documentation-website/pull/7341) +- Add documentation for wildcard field type [#7339](https://github.com/opensearch-project/documentation-website/pull/7339) +- Update document for handle SageMaker throttling [#7331](https://github.com/opensearch-project/documentation-website/pull/7331) +- Add documentation related to new settings for segment upload timeout [#7330](https://github.com/opensearch-project/documentation-website/pull/7330) +- Add documentation of derived fields [#7329](https://github.com/opensearch-project/documentation-website/pull/7329) +- [MDS] Add security analytics, alerting, feature anaywhere in the multiple data source document [#7328](https://github.com/opensearch-project/documentation-website/pull/7328) +- Add document for top n queries improvements in 2.15 [#7326](https://github.com/opensearch-project/documentation-website/pull/7326) +- Update the integration page to reflect new integration catalog features [#7324](https://github.com/opensearch-project/documentation-website/pull/7324) +- Add doc for neural-sparse-query-two-phase-processor. [#7306](https://github.com/opensearch-project/documentation-website/pull/7306) +- Add documentation for Indices Request Cache Overview and its settings [#7288](https://github.com/opensearch-project/documentation-website/pull/7288) +- Added documentation for Reindex workflow step [#7271](https://github.com/opensearch-project/documentation-website/pull/7271) +- Document optional clear_status query parameter for Delete Workflow API [#7268](https://github.com/opensearch-project/documentation-website/pull/7268) +- Update field-masking.md. Configure default masking algorithm. [#7162](https://github.com/opensearch-project/documentation-website/pull/7162) +- add documentation for use compound file setting [#7092](https://github.com/opensearch-project/documentation-website/pull/7092) +- Added documentation for managed identity support in repository-azure plugin [#7068](https://github.com/opensearch-project/documentation-website/pull/7068) + +## In progress documentation for 2.15.0 + +- Initial UBI documentation [#7284](https://github.com/opensearch-project/documentation-website/pull/7284) + +## Documentation for 2.15.0 experimental features + +- Add remote state publication [#7364](https://github.com/opensearch-project/documentation-website/pull/7364)