From 52535111d4a9627d67dcd3497dfc7c70dad061bb Mon Sep 17 00:00:00 2001 From: Simeon Widdis Date: Tue, 28 Mar 2023 11:56:33 -0700 Subject: [PATCH 01/40] Move schema folder to resources Signed-off-by: Simeon Widdis --- src/main/resources/schema/README.md | 81 +++++ .../resources/schema/observability/README.md | 104 +++++++ .../schema/observability/catalog.json | 77 +++++ .../schema/observability/logs/README.md | 235 ++++++++++++++ .../schema/observability/logs/Usage.md | 117 +++++++ .../observability/logs/communication.mapping | 94 ++++++ .../observability/logs/communication.schema | 87 ++++++ .../schema/observability/logs/http.mapping | 115 +++++++ .../schema/observability/logs/http.schema | 92 ++++++ .../schema/observability/logs/logs.mapping | 204 ++++++++++++ .../schema/observability/logs/logs.schema | 216 +++++++++++++ .../logs/sample/http_client-log.json | 16 + .../logs/sample/http_server-log.json | 22 ++ .../logs/sample/nginx_access-log.json | 48 +++ .../schema/observability/metrics/README.md | 105 +++++++ .../observability/metrics/metrics.mapping | 290 ++++++++++++++++++ .../observability/metrics/metrics.schema | 270 ++++++++++++++++ .../observability/metrics/samples/gauge.json | 52 ++++ .../metrics/samples/histogram.json | 65 ++++ .../metrics/samples/load_samples.md | 29 ++ .../observability/metrics/samples/sum.json | 59 ++++ .../schema/observability/traces/README.md | 153 +++++++++ .../traces/samples/load_samples.md | 28 ++ .../observability/traces/samples/traceA.json | 23 ++ .../observability/traces/samples/traceB.json | 51 +++ .../observability/traces/samples/traceC.json | 68 ++++ .../observability/traces/services.mapping | 65 ++++ .../observability/traces/traces.mapping | 200 ++++++++++++ .../schema/observability/traces/traces.schema | 249 +++++++++++++++ src/main/resources/schema/security/README.md | 3 + src/main/resources/schema/system/README.md | 65 ++++ .../schema/system/application.schema | 49 +++ .../resources/schema/system/catalog.schema | 104 +++++++ .../resources/schema/system/datasource.schema | 69 +++++ .../schema/system/index-pattern.schema | 25 ++ .../schema/system/integration-instance.schema | 87 ++++++ .../schema/system/integration.schema | 176 +++++++++++ .../system/integrations-template-list.schema | 41 +++ .../resources/schema/system/notebook.schema | 112 +++++++ .../schema/system/operational-panel.schema | 118 +++++++ .../schema/system/samples/application.json | 17 + .../schema/system/samples/catalog.json | 60 ++++ .../schema/system/samples/datasource.json | 12 + .../schema/system/samples/index-pattern.json | 5 + .../system/samples/integration-instance.json | 19 ++ .../schema/system/samples/integration.json | 46 +++ .../samples/integrations-template-list.json | 23 ++ .../schema/system/samples/notebook.json | 24 ++ .../system/samples/operationalPanel.json | 32 ++ .../schema/system/samples/savedQuery.json | 21 ++ .../schema/system/samples/visualization.json | 30 ++ .../schema/system/saved-query.schema | 97 ++++++ .../schema/system/visualization.schema | 137 +++++++++ 53 files changed, 4587 insertions(+) create mode 100644 src/main/resources/schema/README.md create mode 100644 src/main/resources/schema/observability/README.md create mode 100644 src/main/resources/schema/observability/catalog.json create mode 100644 src/main/resources/schema/observability/logs/README.md create mode 100644 src/main/resources/schema/observability/logs/Usage.md create mode 100644 src/main/resources/schema/observability/logs/communication.mapping create mode 100644 src/main/resources/schema/observability/logs/communication.schema create mode 100644 src/main/resources/schema/observability/logs/http.mapping create mode 100644 src/main/resources/schema/observability/logs/http.schema create mode 100644 src/main/resources/schema/observability/logs/logs.mapping create mode 100644 src/main/resources/schema/observability/logs/logs.schema create mode 100644 src/main/resources/schema/observability/logs/sample/http_client-log.json create mode 100644 src/main/resources/schema/observability/logs/sample/http_server-log.json create mode 100644 src/main/resources/schema/observability/logs/sample/nginx_access-log.json create mode 100644 src/main/resources/schema/observability/metrics/README.md create mode 100644 src/main/resources/schema/observability/metrics/metrics.mapping create mode 100644 src/main/resources/schema/observability/metrics/metrics.schema create mode 100644 src/main/resources/schema/observability/metrics/samples/gauge.json create mode 100644 src/main/resources/schema/observability/metrics/samples/histogram.json create mode 100644 src/main/resources/schema/observability/metrics/samples/load_samples.md create mode 100644 src/main/resources/schema/observability/metrics/samples/sum.json create mode 100644 src/main/resources/schema/observability/traces/README.md create mode 100644 src/main/resources/schema/observability/traces/samples/load_samples.md create mode 100644 src/main/resources/schema/observability/traces/samples/traceA.json create mode 100644 src/main/resources/schema/observability/traces/samples/traceB.json create mode 100644 src/main/resources/schema/observability/traces/samples/traceC.json create mode 100644 src/main/resources/schema/observability/traces/services.mapping create mode 100644 src/main/resources/schema/observability/traces/traces.mapping create mode 100644 src/main/resources/schema/observability/traces/traces.schema create mode 100644 src/main/resources/schema/security/README.md create mode 100644 src/main/resources/schema/system/README.md create mode 100644 src/main/resources/schema/system/application.schema create mode 100644 src/main/resources/schema/system/catalog.schema create mode 100644 src/main/resources/schema/system/datasource.schema create mode 100644 src/main/resources/schema/system/index-pattern.schema create mode 100644 src/main/resources/schema/system/integration-instance.schema create mode 100644 src/main/resources/schema/system/integration.schema create mode 100644 src/main/resources/schema/system/integrations-template-list.schema create mode 100644 src/main/resources/schema/system/notebook.schema create mode 100644 src/main/resources/schema/system/operational-panel.schema create mode 100644 src/main/resources/schema/system/samples/application.json create mode 100644 src/main/resources/schema/system/samples/catalog.json create mode 100644 src/main/resources/schema/system/samples/datasource.json create mode 100644 src/main/resources/schema/system/samples/index-pattern.json create mode 100644 src/main/resources/schema/system/samples/integration-instance.json create mode 100644 src/main/resources/schema/system/samples/integration.json create mode 100644 src/main/resources/schema/system/samples/integrations-template-list.json create mode 100644 src/main/resources/schema/system/samples/notebook.json create mode 100644 src/main/resources/schema/system/samples/operationalPanel.json create mode 100644 src/main/resources/schema/system/samples/savedQuery.json create mode 100644 src/main/resources/schema/system/samples/visualization.json create mode 100644 src/main/resources/schema/system/saved-query.schema create mode 100644 src/main/resources/schema/system/visualization.schema diff --git a/src/main/resources/schema/README.md b/src/main/resources/schema/README.md new file mode 100644 index 000000000..c8202c693 --- /dev/null +++ b/src/main/resources/schema/README.md @@ -0,0 +1,81 @@ +# Simple Schema for Open Search + +## Background +Simple Schema for OpenSearch brings the concept of organized and structured catalog data. +A catalog of schemas is a comprehensive collection of all the possible data schemas or structures that can be used to represent information. + +It provides a standardized way of organizing and describing the structure of data, making it easier to analyze, compare, and share data across different systems and applications. +Structured data refers to any data that is organized in a specific format or schema - for example Observability data or security data... + +By using a catalog of schemas, data analysts and scientists can easily identify and understand the different structures of data, allowing them to correlate and analyze information more effectively. +One of the key benefits of a catalog of schemas is that it promotes interoperability between different systems and applications. +By using standardized schema descriptions, data can be shared and exchanged more easily, regardless of the system or application being used. + +The use of a catalog of schemas can also improve data quality by ensuring that data is consistent and accurate. This is because the schema provides a clear definition of the data structure and the rules for how data should be entered, validated, and stored. + +## OpenSearch Schemas + +Opensearch supports out of the box the following schemas + - [Observability](observability/README.md) + - [Security](security/README.md) + - [System](system/README.md) + +### Observability +Simple Schema for [Observability](https://github.com/opensearch-project/observability) allows ingestion of both (OTEL/ECS) formats and internally consolidate them to best of its capabilities for presenting a unified Observability platform. + +### Security +OpenSearch Security is a [plugin](https://github.com/opensearch-project/security) for OpenSearch that offers encryption, authentication and authorization. When combined with OpenSearch Security-Advanced Modules, it supports authentication via Active Directory, LDAP, Kerberos, JSON web tokens, SAML, OpenID and more. It includes fine grained role-based access control to indices, documents and fields. It also provides multi-tenancy support in OpenSearch Dashboards. + +### System +System represents the internal structure of Opensearch's `.dashboard` entities such as `dashboard`, `notebook`, `save-query` `integration`. Every saved object may declare itself in the system +catalog folder and publish a corresponding schema. This capability will allow validation of these objects and also simplify structure evolution using this schema. + +### Catalog Loading +During Integration plugin loading, it will go over all the Opensearch's schema supported catalogs and generate the appropriate templates representing them. +This will allow any future Integration using these catalogs without the need to explicitly defining them thus maintaining a unified common schema. + +Each catalog may support semantic versioning so that it may evolve its schema as needed. +In the future, the catalog will enable to associate domains with catalogs and allow externally importing catalogs into Opensearch for additional collaboration. + +### Catalog Structure +A catalog is structured in the following way: + + - Catalog named folder: `Observability` + - Categories named folder : `Logs`, `Traces`, `Metrics` + - Component named file : `http` , `communication` , `traces` , `metrics` + +Each level encapsulates additional internal structure that allows a greater level of composability and agility. +The details of each catalog structure is described in the [catalog.json](system/samples/catalog.json) file that resides in the root level of each catalog folder. + +**Component** +The component is the leaf level definition of the catalog hierarchy, it details the actual building blocks of the catalog's types and fields. + +Each component has two flavours: + + - `$component.mapping` - describes how the type is physically stored in the underlying index + - `$component.mapping` - describing the actual json schema for this component type + +A component may be classified as a `container` which has the ability to group / combine multiple components inside. + +For example, we can examine the [`logs`](observability/logs/logs.mapping) component that has the capacity to combine additional components (such as `http`, `communication` and more) +```json5 + ... + "composed_of": [ + "http_template", + "communication_template" + ], + ... +``` +A component also has a list of `tags` which are aliases for the component name which can be used to reference it directly by an integration components list. + +```json5 + ... + { + "component": "communication", + "version": "1.0", + "url": "https://github.com/opensearch-project/observability/tree/2.x/schema/observability/logs/communication", + "tags": ["web"], + "container": false + } + ... +``` \ No newline at end of file diff --git a/src/main/resources/schema/observability/README.md b/src/main/resources/schema/observability/README.md new file mode 100644 index 000000000..5f101d853 --- /dev/null +++ b/src/main/resources/schema/observability/README.md @@ -0,0 +1,104 @@ +# Simple Schema for Observability + +## Background +Observability is the ability to measure a system’s current state based on the data it generates, such as logs, metrics, and traces. Observability relies on telemetry derived from instrumentation that comes from the endpoints and services. + +Observability telemetry signals (logs, metrics, traces) arriving from the system would contain all the necessary information needed to observe and monitor. + +Modern application can have a complicated distributed architecture that combines cloud native and microservices layers. Each layer produces telemetry signals that may have different structure and information. + +Using Simple Schema's Observability telemetry schema we can organize, correlate and investigate system behavior in a standard and well-defined manner. + +Observability telemetry schema defines the following components - **logs, traces and metrics**. + +**Logs** provide comprehensive system details, such as a fault and the specific time when the fault occurred. By analyzing the logs, one can troubleshoot code and identify where and why the error occurred. + +**Traces** represent the entire journey of a request or action as it moves through all the layers of a distributed system. Traces allow you to profile and observe systems, especially containerized applications, serverless architectures, or microservices architecture. + +**Metrics** provide a numerical representation of data that can be used to determine a service or component’s overall behaviour over time. + + +In many occasions, correlation between the logs, traces and metrics is mandatory to be able to monitor and understand how the system is behaving. In addition, the distributed nature of the application produces multiple formats of telemetry signals arriving from different components ( network router, web server, database) + +For such correlation to be possible the industry has formulated several protocols ([OTEL](https://github.com/open-telemetry), [ECS](https://github.com/elastic/ecs), [OpenMetrics](https://github.com/OpenObservability/OpenMetrics)) for communicating these signals - the Observability schemas. + +--- +## Schema Aware Components + +The role of the Observability [plugin](https://github.com/opensearch-project/observability) is intended to allow maximum flexibility and not imposing a strict Index structure of the data source. Nevertheless, the modern nature of distributed application and the vast amount of telemetry producers is changing this perception. + +Today many of the Observability solutions (splunk, datadog, dynatrace) recommend using a consolidated schema to represent the entire variance of log/trace/metrics producers. + +This allows monitoring, incidents investigation and corrections process to become simpler, maintainable and reproducible. + + +A Schema-Aware visualization component is a component which assumes the existence of specific index/indices name patterns and expects these indices to have a specific structure - a schema. + +As an example we can see that **Trace-Analytics** is a schema-aware visual component since it directly assumes the traces & serviceMap indices exist and expects them to follow a specific structure. + +This definition doesn’t change the existing status of visualization components which are not “Schema Aware” but it only regulates which Visual components would benefit using a schema and which will be agnostic of its content. + +Operation Panel for example, are not “Schema Aware” since they don’t assume in advanced the existence of a specific index nor do they expect the index they display to have a specific structure. + +## Data Model + +Simple Schema for Observability allows ingestion of both (OTEL/ECS) formats and internally consolidate them to best of its capabilities for presenting a unified Observability platform. + +## Observability index naming + +The Observability indices would follow the recommended for immutable data stream ingestion pattern using the [data_stream concepts](https://opensearch.org/docs/latest/opensearch/data-streams/) + +Index pattern will follow the next naming template `sso_{type}`-`{dataset}`-`{namespace}` + + - **type** - indicated the observability high level types "logs", "metrics", "traces" (prefixed by the `sso_` schema convention ) + - **dataset** - The field can contain anything that classify the source of the data - such as `nginx.access` + - **namespace** - A user defined namespace - mainly useful to allow grouping of data such as production grade, geography classification + +This strategy allows two degrees of naming freedom: dataset and namespace. For example a customer may want to route the nginx logs from two geographical areas into two different indices: + + - `sso_logs-nginx-us` + - `sso_logs-nginx-eu` + +This type of distinction also allows for creation of crosscutting queries by setting the next index query pattern `sso_logs-nginx-*` or by using a geographic based crosscutting query `sso_logs-*-eu`. + +## Data index routing + +The [ingestion component](https://github.com/opensearch-project/data-prepper) which is responsible for ingesting the Observability signals is responsible to route the data into the relevant indices. + +The `sso_{type}-{dataset}-{namespace}` combination dictates the target index, `{type}` is prefixed with the `sso_` prefix into one of the supported type: + + - Traces - `sso_traces` + - Metrics - `sso_metrics` + - Logs - `sso_logs` + +For example if within the ingested log contains the following section: +```json +{ + ... + "attributes": { + "data_stream": { + "type": "span", + "dataset": "mysql", + "namespace": "prod" + } + } +} +``` +This indicates that the target index for this observability signal should be `sso_traces`-`mysql`-`prod` index that follows uses the traces schema mapping. + +## Observability Index templates + +With the expectation of multiple Observability data providers and the need to consolidate all to a single common schema - the Observability plugin will take the following responsibilities : + + - Define and create all the signals **index templates** upon loading + - Publish a versioned schema file (Json Schema) for each signal type for general validation usage by any 3rd party + +## Observability Ingestion pipeline +The responsibility on an **Observability-ingestion-pipeline** is to create the actual `data_stream` in which it is expecting to ingest into. + +This `data_stream` will use one of the Observability ready-made index templates (Metrics,Traces and Logs) and conform with the above naming pattern (`sso_{type}`-`{dataset}`-`{namespace}`) + +**If the ingesting party has a need to update the template default index setting (shards, replicas ) it may do so before the actual creation of the data_stream.** + +### Note +It is important to mention that these new capabilities would not change or prevent existing customer usage of the system and continue to allow proprietary usage. diff --git a/src/main/resources/schema/observability/catalog.json b/src/main/resources/schema/observability/catalog.json new file mode 100644 index 000000000..66f52e705 --- /dev/null +++ b/src/main/resources/schema/observability/catalog.json @@ -0,0 +1,77 @@ +{ + "catalog": "observability", + "version": "1.0", + "url": "https://github.com/opensearch-project/observability/tree/2.x/schema/observability", + "description": "Observability data catalog is a centralized repository that captures metadata about different data sources and metrics. It provides a comprehensive view of the signals collected from various components of a system and helps identify performance issues. The catalog helps in data discovery, enabling data analysts and engineers to quickly locate and access the required data.It also ensures data quality by enforcing consistent naming conventions, and standardizes data formats to facilitate data analysis and visualization.", + "categories": [ + { + "category": "logs", + "version": "1.0", + "url": "https://github.com/opensearch-project/observability/tree/2.x/schema/observability/logs", + "description": "Observability logs are a type of data that capture the events and activities occurring in a system. They record information such as user actions, system responses, and errors, providing valuable insights into system behavior.Logs can be structured or unstructured, and may include contextual information such as timestamps, unique identifiers, and metadata tags.Logs can be used to troubleshoot issues, detect anomalies, and improve system performance by identifying areas for optimization", + "components": [ + { + "component": "log", + "description": "Observability log is the container for all compound specific log components. It includes timestamp, instrumentation details, provider's resources and attributes and additional metadata, ", + "version": "1.0", + "url": "https://github.com/opensearch-project/observability/tree/2.x/schema/observability/logs/logs", + "container": true, + "tags": [] + }, + { + "component": "http", + "description": "Observability HTTP logs are a type of data that capture information about HTTP requests and responses in a system. They record details such as the request method, URI, response status, and response size. Observability HTTP logs can be used to track user behavior, detect security threats, and monitor system performance. By analyzing HTTP logs, it is possible to identify patterns and anomalies, and to optimize system configuration and behavior for better user experience.", + "version": "1.0", + "url": "https://github.com/opensearch-project/observability/tree/2.x/schema/observability/logs/http", + "tags": [], + "container": false + }, + { + "component": "communication", + "description": "Observability communication covers the host and destination information in the network fields. They contain a set of metadata that provide contextual information about the host, destination and network environment where a system is running. They include information such as the host/destination name, IP address, operating system version, and network interface details.", + "version": "1.0", + "url": "https://github.com/opensearch-project/observability/tree/2.x/schema/observability/logs/communication", + "tags": ["web"], + "container": false + }] + }, + { + "category": "traces", + "description": "Observability traces are a type of data that capture the end-to-end flow of a transaction or request through a system. They include information about the different components and services involved in processing the request, as well as timing and latency data. Traces help identify bottlenecks and performance issues in complex distributed systems, they simplify root cause analysis of issues by providing a detailed view of how a request flows through the system and where delays or errors occur.", + "version": "1.0", + "url": "https://github.com/opensearch-project/observability/tree/2.x/schema/observability/traces", + "components": [ + { + "component": "span", + "description": "Observability spans are a type of data that represent a single unit of work within a trace.They provide information about the execution of a specific operation or function within a service or component.Spans can include timing data, metadata, and contextual information such as error messages or parameters passed to the function, by examining spans within a trace, it is possible to identify specific areas where performance can be optimized or where errors are occurring.", + "version": "1.0", + "url": "https://github.com/opensearch-project/observability/tree/2.x/schema/observability/traces/traces", + "tags": [], + "container": true + }, + { + "component": "service", + "description": "Observability services are representations of the dependencies and interactions between various components of a software system. They provide a high-level view of how different parts of the system are connected and how data flows between them. By using service maps, engineers and developers can gain a better understanding of how changes in one part of the system can affect other parts, helping them make more informed decisions about troubleshooting and optimization including root cause analysis", + "version": "1.0", + "url": "https://github.com/opensearch-project/observability/tree/2.x/schema/observability/traces/services", + "tags": [], + "container": false + }] + }, + { + "category": "metrics", + "description": "Observability metrics are a type of data that capture quantitative measurements of system performance and behavior. They provide information about system resources such as CPU usage, memory consumption, and network traffic. Metrics can be used to track key performance indicators (KPIs) and service level objectives (SLOs), and to monitor system health.By visualizing and analyzing metrics, it is possible to identify trends and anomalies, and to proactively detect and address performance issues before they impact system availability or user experience.", + "version": "1.0", + "url": "https://github.com/opensearch-project/observability/tree/2.x/schema/observability/metrics", + "components": [ + { + "component": "metric", + "description": "There are several types of metrics that exist in observability, including: Counter Metrics, Gauge Metrics ,Histogram Metrics, Exponential Histogram Metrics, Summary Metrics ", + "version": "1.0", + "url": "https://github.com/opensearch-project/observability/tree/2.x/schema/observability/metrics/metrics", + "tags": [], + "container": true + }] + } + ] +} \ No newline at end of file diff --git a/src/main/resources/schema/observability/logs/README.md b/src/main/resources/schema/observability/logs/README.md new file mode 100644 index 000000000..13db0171e --- /dev/null +++ b/src/main/resources/schema/observability/logs/README.md @@ -0,0 +1,235 @@ +# Logs Schema Support + +Observability refers to the ability to monitor and diagnose systems and applications in real-time, in order to understand how they are behaving and identify potential issues. +logs serve as a primary source of information for understanding and debugging complex systems. +Logs provide a record of events, errors, and performance that help developers and administrators identify and resolve issues, monitor system behavior, and improve reliability. + +Logs can also be used to gain insight into user behavior and facilitate auditing and compliance. +By analyzing logs, one can detect patterns, anomalies, and correlations that can inform decisions and facilitate problem-solving. +Logs help to ensure the visibility, reliability, and stability of systems. + +## Details +The next section provides the Simple Schema for Observability support which conforms with the OTEL specification. + +- logs.mapping presents the template mapping for creating the Simple Schema for Observability index +- logs.schema presents the json schema validation for verification of a metrics document conforms to the mapping structure + +## Logs +See [OTEL Logs convention](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/logs/data-model.md) +See [OTEL logs protobuf](https://github.com/open-telemetry/opentelemetry-proto/tree/main/opentelemetry/proto/logs/v1) +See [ECS logs](https://github.com/elastic/ecs) + +Simple Schema for Observability conforms with OTEL logs protocol and also was greatly inspired from the Elastic-Common-Schema schema. + +Simple Schema for Observability defines the next data model: + +## General Fields + +### Event Fields +Within a particular domain, the ```event.name``` attribute identifies the event. Events with same domain and name are structurally similar to one another. +For example, some domains could have well-defined schema for their events based on event names. (OTEL driven) + +`event.kind` gives high-level information about what type of information the event contains, without being specific to the contents of the event.(ECS driven) +**Possible values** + - **alert** - indicates an alerting type event which can be triggered by any alerting mechanism + - **enrichment** - indicates an enriched typed event that adds additional context to the original event + - **event** - the default type of the event + - **metric** - this indicated the event describes a numeric measurement + +The `event.domain` attribute is used to logically separate events from different systems. For example, to record Events from `browser` apps, `mobile` apps and `Kubernetes`, we could use browser, device and k8s as the domain for their Events. +This provides a clean separation of semantics for events in each of the domains. (OTEL driven) + +`event.category` gives categorical-level information about what type of information the event contains, this field is an array. (ECS driven) +**Possible values** + - authentication - events are of a challenge and response process by any system that has such responsibilities + - configuration - events related to the configuration of a system or an application + - database - events that are generated as part of the storage system (SQL RDBMS and such) + - driver - events related to the O/S device driver + - email - events related to email messages, email attachments and such + - file - events related to the fact that it has been created on, or has existed on a filesystem + - host - events related to host inventory or lifecycle events + - iam - Identity & access Management logs types + - network - events relating of network activities (connection / traffic and such) + - package - events indication of software packages installation of hosts + - process - events related to O/S process information + - registry - events related to O/S registry events + - session - events related to a persistent connection between different network components + - web - events related to web server activity + +`event.category` corresponds with `event.domain` + +`event.type` gives a fine grain details of the event's category including the phase in-which the field is part of. +This will allow proper categorization of some events that fall in multiple event types, this field is an array. (ECS driven) + +**Possible values** + - access - indication that this event has accesses some resource + - admin - indication that this event is related to the admin context + - allowed - indication that this event was subsequently allowed by some authority system + - change - indication that this event is related to something that has changed + - connection - indication that this event is related to network traffic with indication of connection activity + - creation - indication that this event is related to resources being created + - deletion - indication that this event is related to resources being deleted + - denied - indication that this event is related to resources being denied access + - error - indication of an error related event + - group - indication of events that are related to group objects + - info - indication of events which are informative without other distinct classification + - installation - indication that this event is related to resources being installed + - protocol - indicate that the event is related to specific knowledge of protocol info + - end - indicate that te event is related to some termination state + - start - indicate that te event is related to some initiation state + - user - indicate that the event is related to specific knowledge a user resource + + +`event.result` gives a success or a failure indication from the perspective of the entity that produced the event. (ECS driven) + +**Possible values** + + - failure + - success + - pending + - undetermined + + +#### Exception Fields +This field encapsulated the exception that should appear under the event section `event.exception` (OTEL driven) + + - `message`: The exception message. + - `stacktrace`: A stacktrace as a string in the natural representation for the language runtime. The representation is to be determined and documented by each language SIG. + - `type`: The type of the exception (its fully-qualified class name, if applicable). The dynamic type of the exception should be preferred over the static type in languages that support it. + +--- + +### Overview + +In observability, Logs are typically unstructured data that is generated by applications or systems as a record of events or messages. +Logs can contain any information that the emitting application or system wants to include, and they often contain free-form text rather than structured data. +This makes logs difficult to process and analyze automatically, but it also provides a lot of flexibility and versatility in terms of what information can be captured. + +According to [ECS](https://github.com/elastic/ecs) and the most recent (experimental) [OTEL](https://github.com/open-telemetry/opentelemetry-specification/tree/main/specification/trace/semantic_conventions) definitions, we formalized a unified +log schema. This schema can be used for working with a well-structured set of typed logs arriving from categorical sources. +These sources are expected to report information in a specific way that will simplify future correlations and consolidate similar concerns. + +### data-stream +[data-stream](https://opensearch.org/docs/latest/opensearch/data-streams/) Data streams simplify this process and enforce a setup that best suits time-series data, such as being designed primarily for append-only data and ensuring that each document has a timestamp field. +A data stream is internally composed of multiple backing indices. Search requests are routed to all the backing indices, while indexing requests are routed to the latest write index. + +As part of the Observability naming scheme, the value of the data stream fields combine to the name of the actual data stream : + +`{data_stream.type}-{data_stream.dataset}-{data_stream.namespace}`. +This means the fields can only contain characters that are valid as part of names of data streams. + + - **type** conforms to one of the supported Observability signals (Traces, Logs, Metrics, Alerts) + - **dataset** user defined field that can mainly be utilized for describing the origin of the signal + - **namespace** user custom field that can be used to describe any customer domain specific classification + +#### Timestamp field +As part of the data-stream definition the `@timestamp` is mandatory, if the field is not present to begin with use `ObservedTimestamp` as value for this field + +### Instrumentation scope +This is a logical unit of the application with which the emitted telemetry can be associated. It is typically the developer’s choice to decide what denotes a reasonable instrumentation scope. +The most common approach is to use the instrumentation library as the scope, however other scopes are also common, e.g. a module, a package, or a class can be chosen as the instrumentation scope. + +The instrumentation scope may have zero or more additional attributes that provide additional information about the scope. As an example the field +`instrumentationScope.attributes.identification` is presented will be used to determine the resource origin of the signal and can be used to filter accordingly + +For Example - in the sample [nginx_access-log.json](sample/nginx_access-log.json) this value equals to `nginx` indicating the signal source. + +This field is expected to appear in any future integration or Observability resources into OpenSearch. + + +### Logs Classifications + +#### HTTP + +_Inspired by [ECS - http](https://www.elastic.co/guide/en/ecs/current/ecs-http.html), [OTEL - http](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/http.md)_ + + - `method` - HTTP request method. `GET; POST; HEAD` (OTEL driven) Correspond with `request.method` (ECS driven) + - `status_code` - [Http response code](https://tools.ietf.org/html/rfc7231#section-6) (OTEL driven) Correspond with `response.status_code` (ECS driven) + - `flavor` - Kind of HTTP protocol used. (OTEL driven) Correspond with `version` (ECS driven) + - `user_agent` - Value of the HTTP User-Agent header sent by the client. (OTEL driven) + + - `request.id` - A unique identifier for each HTTP request to correlate logs between clients and servers in transactions. (ECS driven) + - `request_content_length` - The size of the request payload body in bytes. (OTEL driven) Correspond with `request.bytes` (ECS driven) + - `request.body.content` - The full HTTP request body. (ECS driven) + - `request.referrer` - Referrer for this HTTP request. (ECS driven) + - `request.header` - HTTP request headers key/value object (OTEL driven) + - `request.mime_type` - Mime type of the body of the response. (ECS driven) + + - `response_content_length` - The size of the response payload body in bytes. (OTEL driven) Correspond with `response.bytes` (ECS driven) + - `response.body.content` - The full HTTP response body. (ECS driven) + - `response.header` - HTTP response headers key/value object (OTEL driven) + + - `url` - Full HTTP request URL in the form scheme://host[:port]/path?query[#fragment] (OTEL driven) + - `resend_count` - The ordinal number of request resending attempt (OTEL driven) + + - `scheme` - The URI scheme identifying the used protocol. (OTEL driven) + - `target` - The full request target as passed in a HTTP request line or equivalent. (OTEL driven) + - `route` - The matched route (path template in the format used by the respective server framework) (OTEL driven) + - `client_ip` - The IP address of the original client behind all proxies (OTEL driven) `client.ip` - IP address of the client (IPv4 or IPv6). (ECS driven) + +#### Communication +Includes client / server part of the communication + + **_Inspired by_** : + - [ECS - client](https://www.elastic.co/guide/en/ecs/8.6/ecs-client.html) + - [ECS - Server](https://www.elastic.co/guide/en/ecs/8.6/ecs-server.html#ecs-server) + - [ECS - Source](https://www.elastic.co/guide/en/ecs/8.6/ecs-source.html) + - [ECS - Destination](https://www.elastic.co/guide/en/ecs/8.6/ecs-destination.html) + - [OTEL - network](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/http.md) + + + - `sock.family` - Protocol address family which is used for communication. (OTEL driven) + + - `client.domain` - The domain name of the client system. (ECS driven) Correspond with `source.domain`, (ECS driven) + - `client.bytes` - Bytes sent from the client to the server. (ECS driven) Correspond with `source.bytes` (ECS driven) + - `client.ip` - IP address of the client (IPv4 or IPv6). (ECS driven) Correspond with `source.ip` (ECS driven) + - `client.mac` - MAC address of the client. (IPv4 or IPv6). (ECS driven) Correspond with `source.mac` (ECS driven) + - `client.packets` - Packets sent from the client to the server. (ECS driven) Correspond with `source.packets` (ECS driven) + + - `sock.host.addr` - Local socket address. (OTEL driven) Correspond with `client.address`,`source.address` (ECS driven) + - `sock.host.port` - Local socket port number. (OTEL driven) Corresponds with `client.port`,`source.port` (ECS driven) + + - `server.domain` - The domain name of the server system. (ECS driven) Correspond with `destination.domain` (ECS driven) + - `server.bytes` - Bytes sent from the server to the client. (ECS driven) Correspond with `destination.bytes` (ECS driven) + - `server.ip` - IP address of the server (IPv4 or IPv6). (ECS driven) Correspond with `destination.ip` (ECS driven) + - `server.mac` - MAC address of the server. (IPv4 or IPv6). (ECS driven) Correspond with `destination.mac` (ECS driven) + - `server.packets` - Packets sent from the server to the client.. (ECS driven) Correspond with `destination.packets` (ECS driven) + + - `sock.peer.addr` - Remote socket peer address: IPv4 or IPv6 (OTEL driven) Correspond with `server.address`, `destination.address` (ECS driven) + - `sock.peer.name` - Remote socket peer name. (OTEL driven) Correspond with `destination.domain` (ECS driven) + - `sock.peer.port` - Remote socket peer port. (OTEL driven) (OTEL driven) Corresponds with `server.port`,`destination.port` (ECS driven) + +--- + +```text + + ___________________ + | _______________ | + | |XXXXXXXXXXXXX| | + | |XXXXXXXXXXXXX| | + | |XXXXXXXXXXXXX| | + | |XXXXXXXXXXXXX| | + | |XXXXXXXXXXXXX| | + |_________________| + _[_______]_ + ___[___________]___ + | [_____] []|__ + | [_____] []| \__ + L___________________J \ \___\/ + ___________________ /\ + /###################\ (__) + +``` + +--- + +### References + - https://github.com/opensearch-project/observability/issues/1413 + - https://github.com/opensearch-project/observability/issues/1405 + - https://github.com/opensearch-project/observability/issues/1411 + - https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/logs/semantic_conventions/events.md + - https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/http.md + - https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/http.md + - https://www.elastic.co/guide/en/ecs/8.6/ecs-destination.html + - https://www.elastic.co/guide/en/ecs/8.6/ecs-client.html + - https://www.elastic.co/guide/en/ecs/8.6/ecs-server.html \ No newline at end of file diff --git a/src/main/resources/schema/observability/logs/Usage.md b/src/main/resources/schema/observability/logs/Usage.md new file mode 100644 index 000000000..03fa0c5bb --- /dev/null +++ b/src/main/resources/schema/observability/logs/Usage.md @@ -0,0 +1,117 @@ +# Actual Index setup and usage +The next document describes the practicality of manually defining and initiating of the observability schema indices, it assumes the OpenSearch cluster +is up and running. + +### Setting Up the Logs Mapping +Start the OpenSearch cluster and follow the next steps for manually setup of the Log mapping template: + +`>> PUT _component_template/http_template` + +Copy the http.mapping content [here](http.mapping) + +`>> PUT _component_template/communication_template` + +Copy the communication.mapping content [here](communication.mapping) + +`>> PUT _index_template/logs` + +Copy the logs.mapping content [here](logs.mapping) + +Now you can create an data-stream index (following the logs index pattern) that has the supported schema: + +`>> PUT _data_stream/sso_logs-dataset-test1` + +You can also directly start ingesting data without creating a data stream. +Because we have a matching index template with a data_stream object, OpenSearch automatically creates the data stream: + +`POST sso_logs-dataset-test1/_doc` +```json +{ + "body": "login attempt failed", + "@timestamp": "2013-03-01T00:00:00", + ... +} + +``` + +To see information about a that data stream: +`GET _data_stream/sso_logs-dataset-test1` + +Would respond the following: +```json +{ + "data_streams" : [ + { + "name" : "sso_logs-dataset-test1", + "timestamp_field" : { + "name" : "@timestamp" + }, + "indices" : [ + { + "index_name" : ".ds-sso_logs-dataset-test1-000001", + "index_uuid" : "-VhmuhrQQ6ipYCmBhn6vLw" + } + ], + "generation" : 1, + "status" : "GREEN", + "template" : "sso_logs-*-*" + } + ] +} +``` + +To see more insights about the data stream, use the `_stats` endpoint: +`GET _data_stream/sso_logs-dataset-test1/_stats` +Would respond the following: +```json +{ + "_shards" : { + "total" : 1, + "successful" : 1, + "failed" : 0 + }, + "data_stream_count" : 1, + "backing_indices" : 1, + "total_store_size_bytes" : 208, + "data_streams" : [ + { + "data_stream" : "sso_logs-dataset-test1", + "backing_indices" : 1, + "store_size_bytes" : 208, + "maximum_timestamp" : 0 + } + ] +} +``` +### Ingestion +To ingest data into a data stream, you can use the regular indexing APIs. Make sure every document that you index has a timestamp field. + +`POST sso_logs-dataset-test1/_doc` +```json +{ + "body": "login attempt failed", + "@timestamp": "2013-03-01T00:00:00", + ... +} + +``` +You can search a data stream just like you search a regular index or an index alias. The search operation applies to all of the backing indices (all data present in the stream). + +`GET sso_logs-dataset-test1/_search` +```json +{ + "query": { + "match": { + ... + } + } +} +``` + +### Manage data-streams in OpenSearh + +To manage data streams from OpenSearch Dashboards, open OpenSearch Dashboards, choose Index Management, select Indices or Policy managed indices. + +see additional information: + - https://opensearch.org/docs/latest/opensearch/data-streams/#step-6-manage-data-streams-in-opensearch-dashboards + - https://opensearch.org/docs/latest/opensearch/data-streams/#step-5-rollover-a-data-stream \ No newline at end of file diff --git a/src/main/resources/schema/observability/logs/communication.mapping b/src/main/resources/schema/observability/logs/communication.mapping new file mode 100644 index 000000000..f4325b4b2 --- /dev/null +++ b/src/main/resources/schema/observability/logs/communication.mapping @@ -0,0 +1,94 @@ +{ + "template": { + "mappings": { + "properties": { + "communication": { + "properties": { + "sock.family": { + "type": "keyword", + "ignore_above": 256 + }, + "source": { + "type": "object", + "properties": { + "address": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "domain": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "bytes": { + "type": "long" + }, + "ip": { + "type": "ip" + }, + "port": { + "type": "long" + }, + "mac": { + "type": "keyword", + "ignore_above": 1024 + }, + "packets": { + "type": "long" + } + } + }, + "destination": { + "type": "object", + "properties": { + "address": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "domain": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "bytes": { + "type": "long" + }, + "ip": { + "type": "ip" + }, + "port": { + "type": "long" + }, + "mac": { + "type": "keyword", + "ignore_above": 1024 + }, + "packets": { + "type": "long" + } + } + } + } + } + } + } + } +} \ No newline at end of file diff --git a/src/main/resources/schema/observability/logs/communication.schema b/src/main/resources/schema/observability/logs/communication.schema new file mode 100644 index 000000000..44caf523b --- /dev/null +++ b/src/main/resources/schema/observability/logs/communication.schema @@ -0,0 +1,87 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://opensearch.org/schemas/Communication", + "title": "Communication", + "type": "object", + "properties": { + "source": { + "type": "object", + "properties": { + "sock.family": { + "type": "string" + }, + "source": { + "$ref": "/schemas/Source" + }, + "destination": { + "$ref": "/schemas/Destination" + } + } + }, + "destination": { + "type": "object", + "properties": { + } + }, + "$defs": { + "Source": { + "$id": "/schemas/Source", + "type": "object", + "additionalProperties": true, + "properties": { + "address": { + "type": "string" + }, + "domain": { + "type": "string" + }, + "bytes": { + "type": "integer" + }, + "ip": { + "type": "string" + }, + "port": { + "type": "integer" + }, + "mac": { + "type": "string" + }, + "packets": { + "type": "integer" + } + }, + "title": "Source" + }, + "Destination": { + "$id": "/schemas/Destination", + "type": "object", + "additionalProperties": true, + "properties": { + "address": { + "type": "string" + }, + "domain": { + "type": "string" + }, + "bytes": { + "type": "integer" + }, + "ip": { + "type": "string" + }, + "port": { + "type": "integer" + }, + "mac": { + "type": "string" + }, + "packets": { + "type": "integer" + } + }, + "title": "Destination" + } + } + } +} diff --git a/src/main/resources/schema/observability/logs/http.mapping b/src/main/resources/schema/observability/logs/http.mapping new file mode 100644 index 000000000..f55b3a5f0 --- /dev/null +++ b/src/main/resources/schema/observability/logs/http.mapping @@ -0,0 +1,115 @@ +{ + "template": { + "mappings": { + "dynamic_templates": [ + { + "request_header_map": { + "mapping": { + "type": "keyword" + }, + "path_match": "request.header.*" + } + }, + { + "response_header_map": { + "mapping": { + "type": "keyword" + }, + "path_match": "response.header.*" + } + } + ], + "properties": { + "http": { + "properties": { + "flavor": { + "type": "keyword", + "ignore_above": 256 + }, + "user_agent": { + "type": "keyword", + "ignore_above": 2048 + }, + "url": { + "type": "keyword", + "ignore_above": 2048 + }, + "schema": { + "type": "keyword", + "ignore_above": 1024 + }, + "target": { + "type": "keyword", + "ignore_above": 1024 + }, + "route": { + "type": "keyword", + "ignore_above": 1024 + }, + "client.ip": { + "type": "ip" + }, + "resent_count": { + "type": "integer" + }, + "request": { + "type": "object", + "properties": { + "id": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "body.content": { + "type": "text" + }, + "bytes": { + "type": "long" + }, + "method": { + "type": "keyword", + "ignore_above": 256 + }, + "referrer": { + "type": "keyword", + "ignore_above": 1024 + }, + "mime_type": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "response": { + "type": "object", + "properties": { + "id": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "body.content": { + "type": "text" + }, + "bytes": { + "type": "long" + }, + "status_code": { + "type": "integer" + } + } + } + } + } + } + } + } +} \ No newline at end of file diff --git a/src/main/resources/schema/observability/logs/http.schema b/src/main/resources/schema/observability/logs/http.schema new file mode 100644 index 000000000..85ace4283 --- /dev/null +++ b/src/main/resources/schema/observability/logs/http.schema @@ -0,0 +1,92 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://opensearch.org/schemas/Http", + "title": "Http", + "type": "object", + "properties": { + "request": { + "$ref": "/schemas/Request" + }, + "response": { + "$ref": "/schemas/Response" + }, + "flavor": { + "type": "string" + }, + "user_agent": { + "type": "string" + }, + "url": { + "type": "string" + }, + "schema": { + "type": "string" + }, + "target": { + "type": "string" + }, + "route": { + "type": "string" + }, + "client_ip": { + "type": "string" + }, + "resent_count": { + "type": "integer" + } + }, + "$defs": { + "Request": { + "$id": "/schemas/Request", + "type": "object", + "additionalProperties": true, + "properties": { + "id": { + "type": "string" + }, + "body.content": { + "type": "string" + }, + "bytes": { + "type": "integer" + }, + "method": { + "type": "string" + }, + "referrer": { + "type": "string" + }, + "header": { + "type": "string" + }, + "mime_type": { + "type": "object" + } + }, + "title": "Request" + }, + "Response": { + "$id": "/schemas/Response", + "type": "object", + "additionalProperties": true, + "properties": { + "id": { + "type": "string" + }, + "body.content": { + "type": "string" + }, + "bytes": { + "type": "integer" + }, + "status_code": { + "type": "integer" + }, + "header": { + "type": "object" + } + }, + "title": "Response" + } + } +} diff --git a/src/main/resources/schema/observability/logs/logs.mapping b/src/main/resources/schema/observability/logs/logs.mapping new file mode 100644 index 000000000..2fdac21f5 --- /dev/null +++ b/src/main/resources/schema/observability/logs/logs.mapping @@ -0,0 +1,204 @@ +{ + "index_patterns": [ + "sso_logs-*-*" + ], + "data_stream": {}, + "template": { + "mappings": { + "_meta": { + "version": "1.0.0" + }, + "_source": { + "enabled": true + }, + "dynamic_templates": [ + { + "resources_map": { + "mapping": { + "type": "keyword" + }, + "path_match": "resource.*" + } + }, + { + "attributes_map": { + "mapping": { + "type": "keyword" + }, + "path_match": "attributes.*" + } + }, + { + "instrumentation_scope_attributes_map": { + "mapping": { + "type": "keyword" + }, + "path_match": "instrumentationScope.attributes.*" + } + } + ], + "properties": { + "severity": { + "properties": { + "number": { + "type": "long" + }, + "text": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + } + } + }, + "attributes": { + "type": "object", + "properties": { + "data_stream": { + "properties": { + "dataset": { + "ignore_above": 128, + "type": "keyword" + }, + "namespace": { + "ignore_above": 128, + "type": "keyword" + }, + "type": { + "ignore_above": 56, + "type": "keyword" + } + } + } + } + }, + "body": { + "type": "text" + }, + "@timestamp": { + "type": "date" + }, + "observedTimestamp": { + "type": "date" + }, + "traceId": { + "ignore_above": 256, + "type": "keyword" + }, + "spanId": { + "ignore_above": 256, + "type": "keyword" + }, + "schemaUrl": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "instrumentationScope": { + "properties": { + "name": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 128 + } + } + }, + "version": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "dropped_attributes_count": { + "type": "integer" + }, + "schemaUrl": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + } + } + }, + "event": { + "properties": { + "domain": { + "ignore_above": 256, + "type": "keyword" + }, + "name": { + "ignore_above": 256, + "type": "keyword" + }, + "category": { + "ignore_above": 256, + "type": "keyword" + }, + "type": { + "ignore_above": 256, + "type": "keyword" + }, + "kind": { + "ignore_above": 256, + "type": "keyword" + }, + "result": { + "ignore_above": 256, + "type": "keyword" + }, + "exception": { + "properties": { + "message": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 256, + "type": "keyword" + }, + "stacktrace": { + "type": "text" + } + } + } + } + } + } + }, + "settings": { + "index": { + "mapping": { + "total_fields": { + "limit": 10000 + } + }, + "refresh_interval": "5s" + } + } + }, + "composed_of": [ + "http_template", + "communication_template" + ], + "version": 1, + "_meta": { + "description": "Simple Schema For Observability", + "catalog": "observability", + "type": "logs" + } +} \ No newline at end of file diff --git a/src/main/resources/schema/observability/logs/logs.schema b/src/main/resources/schema/observability/logs/logs.schema new file mode 100644 index 000000000..c014c12ac --- /dev/null +++ b/src/main/resources/schema/observability/logs/logs.schema @@ -0,0 +1,216 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://opensearch.org#/definitions/Logs", + "title": "OpenTelemetry Logs", + "type": "object", + "properties": { + "severity": { + "$ref": "#/definitions/Severity" + }, + "resource": { + "type": "object" + }, + "attributes": { + "$ref": "#/definitions/Attributes" + }, + "body": { + "type": "string" + }, + "@timestamp": { + "type": "string", + "format": "date-time" + }, + "observedTimestamp": { + "type": "string", + "format": "date-time" + }, + "traceId": { + "type": "string" + }, + "spanId": { + "type": "string" + }, + "schemaUrl": { + "type": "string" + }, + "instrumentationScope": { + "$ref": "#/definitions/InstrumentationScope" + }, + "event": { + "$ref": "#/definitions/Event" + } + }, + "required": [ + "body", + "@timestamp" + ], + "definitions": { + "InstrumentationScope": { + "$id": "#/definitions/InstrumentationScope", + "type": "object", + "additionalProperties": true, + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "schemaUrl": { + "type": "string" + } + }, + "title": "InstrumentationScope" + }, + "Severity": { + "$id": "#/definitions/Severity", + "type": "object", + "additionalProperties": true, + "properties": { + "text": { + "type": "string", + "enum": [ + "TRACE", + "DEBUG", + "INFO", + "WARN", + "ERROR", + "FATAL" + ] + }, + "number": { + "type": "integer" + } + }, + "title": "Severity" + }, + "Attributes": { + "$id": "#/definitions/Attributes", + "type": "object", + "additionalProperties": true, + "properties": { + "data_stream": { + "$ref": "#/definitions/Dataflow" + } + }, + "title": "Attributes" + }, + "Dataflow": { + "$id": "#/definitions/Dataflow", + "type": "object", + "additionalProperties": true, + "properties": { + "type": { + "type": "string" + }, + "namespace": { + "type": "string" + }, + "dataset": { + "type": "string" + } + }, + "title": "Dataflow" + }, + "Exception": { + "$id": "#/definitions/Exception", + "type": "object", + "additionalProperties": true, + "properties": { + "message": { + "type": "string" + }, + "stacktrace": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "title": "Exception" + }, + "Event": { + "$id": "#/definitions/Event", + "type": "object", + "additionalProperties": true, + "properties": { + "category": { + "type": "string", + "enum": [ + "authentication", + "configuration", + "database", + "driver", + "email", + "file", + "host", + "iam", + "intrusion_detection", + "malware", + "network", + "package", + "process", + "registry", + "session", + "threat", + "vulnerability", + "web" + ] + }, + "kind": { + "type": "string", + "enum": [ + "alert", + "enrichment", + "event", + "metric", + "state", + "pipeline_error", + "signal" + ] + }, + "type": { + "type": "string", + "enum": [ + "access", + "admin", + "allowed", + "change", + "connection", + "creation", + "deletion", + "denied", + "end", + "error", + "group", + "indicator", + "info", + "installation", + "protocol", + "start", + "user" + ] + }, + "domain": { + "type": "string" + }, + "name": { + "type": "string" + }, + "result": { + "type": "string", + "enum": [ + "failure", + "success", + "pending", + "undetermined" + ] + }, + "exception": { + "$ref": "#/definitions/Exception" + } + }, + "title": "Event" + } + } +} \ No newline at end of file diff --git a/src/main/resources/schema/observability/logs/sample/http_client-log.json b/src/main/resources/schema/observability/logs/sample/http_client-log.json new file mode 100644 index 000000000..14981a5cf --- /dev/null +++ b/src/main/resources/schema/observability/logs/sample/http_client-log.json @@ -0,0 +1,16 @@ +{ + "@timestamp": "2022-12-09T10:39:23.000Z", + "http": { + "method": "GET", + "flavor": "1.1", + "url": "https://example.com:8080/webshop/articles/4?s=1" + }, + "destination": { + "domain": "example.com", + "address": "192.0.2.5", + "port": 8080 + }, + "response": { + "status_code": 200 + } +} \ No newline at end of file diff --git a/src/main/resources/schema/observability/logs/sample/http_server-log.json b/src/main/resources/schema/observability/logs/sample/http_server-log.json new file mode 100644 index 000000000..95710445d --- /dev/null +++ b/src/main/resources/schema/observability/logs/sample/http_server-log.json @@ -0,0 +1,22 @@ +{ + "@timestamp": "2022-12-09T10:39:23.000Z", + "http": { + "method": "GET", + "flavor": "1.1", + "target": "https://example.com:8080/webshop/articles/4?s=1", + "schema": "https", + "route": "https", + "client.ip": "192.0.2.4", + "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:72.0) Gecko/20100101 Firefox/72.0" + }, + "source": { + "domain": "example.com", + "port": 8080 + }, + "destination": { + "address": "192.0.2.5" + }, + "response": { + "status_code": 200 + } +} \ No newline at end of file diff --git a/src/main/resources/schema/observability/logs/sample/nginx_access-log.json b/src/main/resources/schema/observability/logs/sample/nginx_access-log.json new file mode 100644 index 000000000..2cc58b7e5 --- /dev/null +++ b/src/main/resources/schema/observability/logs/sample/nginx_access-log.json @@ -0,0 +1,48 @@ +{ + "@timestamp": "2022-12-09T10:39:23.000Z", + "observedTimestamp": "2022-12-09T10:39:38.896Z", + "body": "47.29.201.179 - - [01/Mar/2020:10:34:43 +0100] \"GET / HTTP/1.1\" 200 612 \"-\" \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.119 Safari/537.36\"", + "trace_id":"102981ABCD2901", + "span_id":"abcdef1010", + "instrumentationScope":{ + "attributes": { + "identification": "nginx" + } + }, + "attributes": { + "data_stream": { + "dataset": "nginx.access", + "namespace": "production", + "type": "logs" + } + }, + "event": { + "category": [ + "web" + ], + "name": "access", + "domain": "nginx.access", + "kind": "event", + "result": "success", + "type": [ + "access" + ] + }, + "http": { + "request": { + "method": "GET" + }, + "response": { + "bytes": 97, + "status_code": 200 + }, + "flavor": "1.1", + "url": "/server-status" + }, + "communication": { + "source": { + "address": "127.0.0.1", + "ip": "127.0.0.1" + } + } +} \ No newline at end of file diff --git a/src/main/resources/schema/observability/metrics/README.md b/src/main/resources/schema/observability/metrics/README.md new file mode 100644 index 000000000..78e940f51 --- /dev/null +++ b/src/main/resources/schema/observability/metrics/README.md @@ -0,0 +1,105 @@ +# Metrics Schema Support + +Observability refers to the ability to monitor and diagnose systems and applications in real-time, in order to understand how they are behaving and identify potential issues. +Metrics present a critical component of observability, providing quantifiable data about the performance and behavior of systems and applications. +The importance of supporting metrics structured schema lies in the fact that it enables better analysis and understanding of system behavior. + +A structured schema provides a clear, consistent format, making it easier for observability tools to process and aggregate the data. +This in turn makes it easier for engineers to understand the performance and behavior of their systems, and quickly identify potential issues. + +When metrics are unstructured, it can be difficult for observability tools to extract meaningful information from them. +For example, if the data for a particular metric is not consistently recorded in the same format, it can be difficult to compare and analyze performance data over time. +Similarly, if metrics are not consistently named or categorized, it can be difficult to understand their context and significance. + +With a structured schema in place, observability tools can automatically extract and aggregate data, making it easier to understand system behavior at a high level. +This can help teams quickly identify performance bottlenecks, track changes in system behavior over time, and make informed decisions about system performance optimization. + +## Details +The next section provides the Simple Schema for Observability support which conforms with the OTEL specification. + +- metrics.mapping presents the template mapping for creating the Simple Schema for Observability index +- metrics.schema presents the json schema validation for verification of a metrics document conforms to the mapping structure + +## Metrics +see [OTEL metrics convention](https://opentelemetry.io/docs/reference/specification/metrics/) +see [OTEL metrics protobuf](https://github.com/open-telemetry/opentelemetry-proto/tree/main/opentelemetry/proto/metrics/v1) + +Simple Schema for Observability conforms with OTEL metrics protocol which defines the next data model: + +#### Timestamp field +As part of the data-stream definition the `@timestamp` is mandatory, if the field is not present in the original signal populate this field using `ObservedTimestamp` as value. + +### Instrumentation scope +This is a logical unit of the application with which the emitted telemetry can be associated. It is typically the developer’s choice to decide what denotes a reasonable instrumentation scope. +The most common approach is to use the instrumentation library as the scope, however other scopes are also common, e.g. a module, a package, or a class can be chosen as the instrumentation scope. + +The instrumentation scope may have zero or more additional attributes that provide additional information about the scope. As an example the field +`instrumentationScope.attributes.identification` is presented will be used to determine the resource origin of the signal and can be used to filter accordingly + +### Overview +Metrics are a specific kind of telemetry data. They represent a snapshot of the current state for a set of data. +Metrics are distinct from logs or events, which focus on records or information about individual events. + +Metrics expresses all system states as numerical values; counts, current values and such. +Metrics tend to aggregate data temporally, while this can lose information, the reduction in overhead is an engineering trade-off commonly chosen in many modern monitoring systems. + +Time series are a record of changing information over time. While time series can support arbitrary strings or binary data, only numeric data is in our scope. +Common examples of metric time series would be network interface counters, device temperatures, BGP connection states, and alert states. + +### Metric streams +In a similar way to the data_stream attribute field representing the category of a trace, the metric streams are grouped into individual Metric objects, identified by: + + - The originating Resource attributes + - The instrumentation Scope (e.g., instrumentation library name, version) + - The metric stream’s name + +### Metrics +Metric object is defined by the following properties: + + - The data point type (e.g. Sum, Gauge, Histogram ExponentialHistogram, Summary) + - The metric stream’s unit + - The data point properties, where applicable: AggregationTemporality, Monotonic + +The description is also present in the metrics object but is not part of the identification fields +_- The metric stream’s description_ + + +### Data Types + +**Values:** Metric values in MUST be either floating points or integers. + +**Attributes:** Labels are key-value pairs consisting of string as keys and Any type as values (strings, object, array) + +**MetricPoint:** Each MetricPoint consists of a set of values, depending on the MetricFamily type. + +**Metric** Metrics are defined by a unique attributes (dimensions) within a MetricFamily. + +--- + +Metrics MUST contain a list of one or more MetricPoints. Metrics with the same name for a given MetricFamily SHOULD have the same set of label names in their LabelSet. + +* Metrics.name: String value representation of the matrix purpose +* Metrics.type: Valid values are "gauge", "counter","histogram", and "summary". +* Metrics.Unit: specifies MetricFamily units. + +## Metric Types + +### Gauge +Gauges are current measurements, such as bytes of memory currently used or the number of items in a queue. For gauges the absolute value is what is of interest to a user. +**_A MetricPoint in a Metric with the type gauge MUST have a single value._** +Gauges MAY increase, decrease, or stay constant over time. Even if they only ever go in one direction, they might still be gauges and not counters. + +### Counter +Counters measure discrete events. Common examples are the number of HTTP requests received, CPU seconds spent, or bytes sent. For counters how quickly they are increasing over time is what is of interest to a user. +**_A MetricPoint in a Metric with the type Counter MUST have one value called Total._** + +### Histogram / Exponential-Histogram +Histograms measure distributions of discrete events. Common examples are the latency of HTTP requests, function runtimes, or I/O request sizes. +**_A Histogram MetricPoint MUST contain at least one bucket_**, and SHOULD contain Sum, and Created values. Every bucket MUST have a threshold and a value. + +### Summary +Summaries also measure distributions of discrete events and MAY be used when Histograms are too expensive and/or an average event size is sufficient. +**_A Summary MetricPoint MAY consist of a Count, Sum, Created, and a set of quantiles._** +Semantically, Count and Sum values are counters & MUST be an integer. + + diff --git a/src/main/resources/schema/observability/metrics/metrics.mapping b/src/main/resources/schema/observability/metrics/metrics.mapping new file mode 100644 index 000000000..0e66087a0 --- /dev/null +++ b/src/main/resources/schema/observability/metrics/metrics.mapping @@ -0,0 +1,290 @@ +{ + "index_patterns": [ + "sso_metrics-*-*" + ], + "data_stream": {}, + "template": { + "mappings": { + "_meta": { + "version": "1.0.0" + }, + "_source": { + "enabled": true + }, + "dynamic_templates": [ + { + "attributes_map": { + "mapping": { + "type": "keyword" + }, + "path_match": "attributes.*" + } + }, + { + "resources_map": { + "mapping": { + "type": "keyword" + }, + "path_match": "resource.*" + } + }, + { + "exemplar_attributes_map": { + "mapping": { + "type": "keyword" + }, + "path_match": "exemplar.attributes.*" + } + }, + { + "instrumentation_scope_attributes_map": { + "mapping": { + "type": "keyword" + }, + "path_match": "instrumentationScope.attributes.*" + } + } + ], + "properties": { + "name": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "attributes": { + "type": "object", + "properties": { + "data_stream": { + "properties": { + "dataset": { + "ignore_above": 128, + "type": "keyword" + }, + "namespace": { + "ignore_above": 128, + "type": "keyword" + }, + "type": { + "ignore_above": 56, + "type": "keyword" + } + } + } + } + }, + "description": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "unit": { + "type": "keyword", + "ignore_above": 128 + }, + "kind": { + "type": "keyword", + "ignore_above": 128 + }, + "aggregationTemporality": { + "type": "keyword", + "ignore_above": 128 + }, + "monotonic": { + "type": "boolean" + }, + "startTime": { + "type": "date" + }, + "@timestamp": { + "type": "date" + }, + "observedTimestamp": { + "type": "date_nanos" + }, + "value": { + "properties": { + "int": { + "type": "integer" + }, + "double": { + "type": "double" + } + } + }, + "buckets": { + "properties": { + "count": { + "type": "long" + }, + "sum": { + "type": "double" + }, + "max": { + "type": "float" + }, + "min": { + "type": "float" + } + } + }, + "bucketCount": { + "type": "long" + }, + "bucketCountsList": { + "type": "long" + }, + "explicitBoundsList": { + "type": "float" + }, + "explicitBoundsCount": { + "type": "float" + }, + "quantiles": { + "properties": { + "quantile": { + "type": "double" + }, + "value": { + "type": "double" + } + } + }, + "quantileValuesCount": { + "type": "long" + }, + "positiveBuckets": { + "properties": { + "count": { + "type": "long" + }, + "max": { + "type": "float" + }, + "min": { + "type": "float" + } + } + }, + "negativeBuckets": { + "properties": { + "count": { + "type": "long" + }, + "max": { + "type": "float" + }, + "min": { + "type": "float" + } + } + }, + "negativeOffset": { + "type": "integer" + }, + "positiveOffset": { + "type": "integer" + }, + "zeroCount": { + "type": "long" + }, + "scale": { + "type": "long" + }, + "max": { + "type": "float" + }, + "min": { + "type": "float" + }, + "sum": { + "type": "float" + }, + "count": { + "type": "long" + }, + "exemplar": { + "properties": { + "time": { + "type": "date" + }, + "traceId": { + "ignore_above": 256, + "type": "keyword" + }, + "spanId": { + "ignore_above": 256, + "type": "keyword" + } + } + }, + "instrumentationScope": { + "properties": { + "name": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 128 + } + } + }, + "version": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "droppedAttributesCount": { + "type": "integer" + }, + "schemaUrl": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + } + } + }, + "schemaUrl": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + } + } + }, + "settings": { + "index": { + "mapping": { + "total_fields": { + "limit": 10000 + } + }, + "refresh_interval": "5s" + } + } + }, + "version": 1, + "_meta": { + "description": "Observability Metrics Mapping Template", + "catalog": "observability", + "type": "metrics" + } +} \ No newline at end of file diff --git a/src/main/resources/schema/observability/metrics/metrics.schema b/src/main/resources/schema/observability/metrics/metrics.schema new file mode 100644 index 000000000..27a8cd044 --- /dev/null +++ b/src/main/resources/schema/observability/metrics/metrics.schema @@ -0,0 +1,270 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://opensearch.org#/definitions/Metrics", + "title": "OpenTelemetry Metrics", + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "attributes": { + "$ref": "#/definitions/Attributes" + }, + "resource": { + "type": "object" + }, + "description": { + "type": "string" + }, + "unit": { + "type": "string" + }, + "kind": { + "type": "string", + "enum": [ + "COUNTER", + "SUM", + "GAUGE", + "HISTOGRAM", + "EXPONENTIAL_HISTOGRAM" + ] + }, + "aggregationTemporality": { + "type": "string", + "enum": [ + "AGGREGATION_TEMPORALITY_UNSPECIFIED", + "AGGREGATION_TEMPORALITY_DELTA", + "AGGREGATION_TEMPORALITY_CUMULATIVE" + ] + }, + "monotonic": { + "type": "boolean" + }, + "startTime": { + "type": "string", + "format": "date-time" + }, + "@timestamp": { + "type": "string", + "format": "date-time" + }, + "observedTimestamp": { + "type": "string", + "format": "date-time" + }, + "value.int": { + "type": "integer" + }, + "value.double": { + "type": "number" + }, + "buckets": { + "type": "array", + "items": { + "$ref": "#/definitions/Bucket" + } + }, + "bucketCount": { + "type": "integer" + }, + "bucketCountsList": { + "type": "array", + "items": { + "type": "number" + } + }, + "explicitBoundsCount": { + "type": "integer" + }, + "explicitBoundsList": { + "type": "array", + "items": { + "type": "number" + } + }, + "quantiles": { + "type": "array", + "items": { + "$ref": "#/definitions/Quantile" + } + }, + "quantileValuesCount": { + "type": "number" + }, + "positiveBuckets": { + "type": "array", + "items": { + "$ref": "#/definitions/Bucket" + } + }, + "negativeBuckets": { + "type": "array", + "items": { + "$ref": "#/definitions/Bucket" + } + }, + "positiveOffset": { + "type": "array", + "items": { + "type": "number" + } + }, + "negativeOffset": { + "type": "array", + "items": { + "type": "number" + } + }, + "zeroCount": { + "type": "number" + }, + "scale": { + "type": "integer" + }, + "max": { + "type": "number" + }, + "min": { + "type": "number" + }, + "sum": { + "type": "number" + }, + "count": { + "type": "number" + }, + "exemplars": { + "type": "array", + "items": { + "$ref": "#/definitions/Exemplar" + } + }, + "instrumentationScope": { + "$ref": "#/definitions/InstrumentationScope" + }, + "schemaUrl": { + "type": "string" + } + }, + "required": [ + "name", + "description", + "unit", + "kind", + "@timestamp" + ], + "definitions": { + "Bucket": { + "$id": "#/definitions/Bucket", + "type": "object", + "additionalProperties": false, + "properties": { + "count": { + "type": "number" + }, + "sum": { + "type": "number" + }, + "max": { + "type": "number" + }, + "min": { + "type": "number" + } + }, + "required": [ + "count", + "max", + "min" + ], + "title": "Bucket" + }, + "Quantile": { + "$id": "#/definitions/Quantile", + "type": "object", + "additionalProperties": false, + "properties": { + "quantile": { + "type": "number" + }, + "value": { + "type": "number" + } + }, + "required": [ + "quantile", + "value" + ], + "title": "Quantile" + }, + "InstrumentationScope": { + "$id": "#/definitions/InstrumentationScope", + "type": "object", + "additionalProperties": true, + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "schemaUrl": { + "type": "string" + }, + "droppedAttributesCount": { + "type": "integer" + } + }, + "title": "InstrumentationScope" + }, + "Exemplar": { + "$id": "/definitions/Exemplar", + "type": "object", + "additionalProperties": true, + "properties": { + "time": { + "type": "string", + "format": "date-time" + }, + "spanId": { + "type": "string" + }, + "traceId": { + "type": "string" + } + }, + "required": [ + "time" + ], + "title": "Exemplar" + }, + "Attributes": { + "$id": "/definitions/Attributes", + "type": "object", + "additionalProperties": true, + "properties": { + "data_stream": { + "$ref": "#/definitions/Dataflow" + } + }, + "title": "Attributes" + }, + "Dataflow": { + "$id": "/definitions/Dataflow", + "type": "object", + "additionalProperties": true, + "properties": { + "type": { + "type": "string" + }, + "namespace": { + "type": "string" + }, + "dataset": { + "type": "string" + } + }, + "title": "Dataflow" + } + } +} \ No newline at end of file diff --git a/src/main/resources/schema/observability/metrics/samples/gauge.json b/src/main/resources/schema/observability/metrics/samples/gauge.json new file mode 100644 index 000000000..e8ec59070 --- /dev/null +++ b/src/main/resources/schema/observability/metrics/samples/gauge.json @@ -0,0 +1,52 @@ +{ + "unit": "ms", + "exemplars": [], + "kind": "GAUGE", + "name": "lastLatency", + "flags": 0, + "description": "The last API latency observed at collection interval", + "startTime": "2023-01-20T05:16:16.425669Z", + "@timestamp": "2023-01-20T05:16:16.425669Z", + "value.double": 0.0, + "resource": { + "cloud@account@id": "123367104812", + "process@pid": 1, + "host@arch": "amd64", + "host@id": "i-0005de88c8ebe7dbb", + "host@image@id": "ami-093d4bc1f6d4a890b", + "telemetry@sdk@version": "1.19.0", + "service@name": "AOCDockerDemoService", + "process@runtime@name": "OpenJDK Runtime Environment", + "os@type": "linux", + "cloud@availability_zone": "us-west-2b", + "host@type": "c5.2xlarge", + "cloud@provider": "aws", + "telemetry@sdk@language": "java", + "host@name": "ip-172-16-42-233.amazon.com", + "process@runtime@description": "Debian OpenJDK 64-Bit Server VM 17.0.4+8-Debian-1deb11u1", + "service@namespace": "AOCDockerDemo", + "cloud@region": "us-west-2", + "process@executable@path": "/usr/lib/jvm/java-17-openjdk-amd64/bin/java", + "process@command_line": "/usr/lib/jvm/java-17-openjdk-amd64/bin/java -javaagent:/aws-observability/classpath/aws-opentelemetry-agent-1.19.0-SNAPSHOT.jar", + "process@runtime@version": "17.0.4+8-Debian-1deb11u1", + "cloud@platform": "aws_ec2", + "telemetry@sdk@name": "opentelemetry", + "container@id": "71301ad845e7d082911d846ac9af3cd9ba4f2144d82d7ac0dfd51f335b256a61", + "telemetry@auto@version": "1.19.0-aws-SNAPSHOT", + "os@description": "Linux 5.4.225-139.416.amzn2int.x86_64" + }, + "attributes": { + "statusCode": "", + "apiName": "", + "serviceName": "AOCDockerDemoService" + }, + + "instrumentationScope": { + "version": "1.0", + "name": "aws-otel", + "schemaUrl": "https://opentelemetry.io/schemas/1.13.0", + "attributes": { + "identification": "aws-ec2" + } + } +} diff --git a/src/main/resources/schema/observability/metrics/samples/histogram.json b/src/main/resources/schema/observability/metrics/samples/histogram.json new file mode 100644 index 000000000..3814aedb9 --- /dev/null +++ b/src/main/resources/schema/observability/metrics/samples/histogram.json @@ -0,0 +1,65 @@ +{ + "max": 652094078, + "kind": "HISTOGRAM", + "buckets": [ + { + "min": 3.4028234663852886e+38, + "max": 0, + "count": 0 + }, + { + "min": 0, + "max": 10000000, + "count": 0 + }, + { + "min": 10000000, + "max": 50000000, + "count": 5 + }, + { + "min": 50000000, + "max": 100000000, + "count": 1 + }, + { + "min": 100000000, + "max": 3.4028234663852886e+38, + "count": 10 + } + ], + "count": 16, + "bucketCountsList": [ + 0, + 0, + 5, + 1, + 10 + ], + "description": "Histogram of durationInNanos in the events", + "sum": 3136355061, + "unit": "seconds", + "aggregationTemporality": "AGGREGATION_TEMPORALITY_DELTA", + "min": 44606914, + "bucketCounts": 5, + "name": "histogram", + "startTime": "2023-01-20T05:16:16.425669Z", + "explicitBoundsCount": 4, + "@timestamp": "2023-01-20T05:16:16.425669Z", + "explicitBoundsList": [ + 0, + 10000000, + 50000000, + 100000000 + ], + "attributes": { + "aggr_duration": 26709005000, + "serviceName": "AOCDockerDemoService", + "histogram_key": "durationInNanos", + "data_stream": { + "dataset": "histogram", + "namespace": "production", + "type": "metric" + } + } +} \ No newline at end of file diff --git a/src/main/resources/schema/observability/metrics/samples/load_samples.md b/src/main/resources/schema/observability/metrics/samples/load_samples.md new file mode 100644 index 000000000..96f1af7c6 --- /dev/null +++ b/src/main/resources/schema/observability/metrics/samples/load_samples.md @@ -0,0 +1,29 @@ +## Load samples +For loading the given samples run the next request once the Opensearch cluster including Observability plugin has started: + + +`PUT sso_metrics-default-namespace/_bulk` +```json +{ "create":{ } } +{"max":652094078,"kind":"HISTOGRAM","buckets":[{"min":3.4028234663852886e+38,"max":0,"count":0},{"min":0,"max":10000000,"count":0},{"min":10000000,"max":50000000,"count":5},{"min":50000000,"max":100000000,"count":1},{"min":100000000,"max":3.4028234663852886e+38,"count":10}],"count":16,"bucketCountsList":[0,0,5,1,10],"description":"Histogram of durationInNanos in the events","sum":3136355061,"unit":"seconds","aggregationTemporality":"AGGREGATION_TEMPORALITY_DELTA","min":44606914,"bucketCounts":5,"name":"histogram","startTime":"2023-01-20T05:16:16.425669Z","explicitBoundsCount":4,"@timestamp":"2023-01-20T05:16:16.425669Z","explicitBoundsList":[0,10000000,50000000,100000000],"attributes":{"aggr_duration":26709005000,"serviceName":"AOCDockerDemoService","histogram_key":"durationInNanos","data_stream":{"dataset":"histogram","namespace":"production","type":"metric"}}} +{ "create":{ } } +{"unit":"ms","exemplars":[],"kind":"GAUGE","name":"lastLatency","flags":0,"description":"The last API latency observed at collection interval","startTime":"2023-01-20T05:16:16.425669Z","@timestamp":"2023-01-20T05:16:16.425669Z","value.double":0,"resource":{"cloud@account@id":"123367104812","process@pid":1,"host@arch":"amd64","host@id":"i-0005de88c8ebe7dbb","host@image@id":"ami-093d4bc1f6d4a890b","telemetry@sdk@version":"1.19.0","service@name":"AOCDockerDemoService","process@runtime@name":"OpenJDK Runtime Environment","os@type":"linux","cloud@availability_zone":"us-west-2b","host@type":"c5.2xlarge","cloud@provider":"aws","telemetry@sdk@language":"java","host@name":"ip-172-16-42-233.amazon.com","process@runtime@description":"Debian OpenJDK 64-Bit Server VM 17.0.4+8-Debian-1deb11u1","service@namespace":"AOCDockerDemo","cloud@region":"us-west-2","process@executable@path":"/usr/lib/jvm/java-17-openjdk-amd64/bin/java","process@command_line":"/usr/lib/jvm/java-17-openjdk-amd64/bin/java -javaagent:/aws-observability/classpath/aws-opentelemetry-agent-1.19.0-SNAPSHOT.jar","process@runtime@version":"17.0.4+8-Debian-1deb11u1","cloud@platform":"aws_ec2","telemetry@sdk@name":"opentelemetry","container@id":"71301ad845e7d082911d846ac9af3cd9ba4f2144d82d7ac0dfd51f335b256a61","telemetry@auto@version":"1.19.0-aws-SNAPSHOT","os@description":"Linux 5.4.225-139.416.amzn2int.x86_64"},"attributes":{"statusCode":"","apiName":"","serviceName":"AOCDockerDemoService"},"instrumentationScope":{"version":"1.0","name":"aws-otel","schemaUrl":"https://opentelemetry.io/schemas/1.13.0","attributes":{"identification":"aws-ec2"}}} +{ "create":{ } } +{"kind":"SUM","flags":0,"description":"Queue Size change","monotonic":false,"unit":"one","aggregationTemporality":"AGGREGATION_TEMPORALITY_CUMULATIVE","exemplars":[],"name":"queueSizeChange","startTime":"2023-01-20T05:16:16.425669Z","@timestamp":"2023-01-20T05:16:16.425669Z","value.double":0,"resource":{"cloud@account@id":"123367104812","process@pid":1,"host@arch":"amd64","host@id":"i-0005de88c8ebe7dbb","host@image@id":"ami-093d4bc1f6d4a890b","telemetry@sdk@version":"1.19.0","service@name":"AOCDockerDemoService","process@runtime@name":"OpenJDK Runtime Environment","os@type":"linux","cloud@availability_zone":"us-west-2b","host@type":"c5.2xlarge","cloud@provider":"aws","telemetry@sdk@language":"java","host@name":"ip-172-16-42-233.amazon.com","process@runtime@description":"Debian OpenJDK 64-Bit Server VM 17.0.4+8-Debian-1deb11u1","service@namespace":"AOCDockerDemo","cloud@region":"us-west-2","process@executable@path":"/usr/lib/jvm/java-17-openjdk-amd64/bin/java","process@command_line":"/usr/lib/jvm/java-17-openjdk-amd64/bin/java -javaagent:/aws-observability/classpath/aws-opentelemetry-agent-1.19.0-SNAPSHOT.jar","process@runtime@version":"17.0.4+8-Debian-1deb11u1","cloud@platform":"aws_ec2","telemetry@sdk@name":"opentelemetry","container@id":"71301ad845e7d082911d846ac9af3cd9ba4f2144d82d7ac0dfd51f335b256a61","telemetry@auto@version":"1.19.0-aws-SNAPSHOT","os@description":"Linux 5.4.225-139.416.amzn2int.x86_64"},"instrumentationScope":{"version":"1.0","name":"aws-otel","schemaUrl":"https://opentelemetry.io/schemas/1.13.0","attributes":{"identification":"aws-ec2"}},"attributes":{"serviceName":"AOCDockerDemoService","statusCode":"","apiName":"","data_stream":{"dataset":"sum","namespace":"production","type":"metric"}}} +``` + +- Run the next query to get the Histogram type metrics: + +- `GET sso_metrics-default-namespace/_search` +```json +{ + "query":{ + "term": { + "kind":{ + "value":"HISTOGRAM" + } + } + } +} + +``` \ No newline at end of file diff --git a/src/main/resources/schema/observability/metrics/samples/sum.json b/src/main/resources/schema/observability/metrics/samples/sum.json new file mode 100644 index 000000000..35e319b56 --- /dev/null +++ b/src/main/resources/schema/observability/metrics/samples/sum.json @@ -0,0 +1,59 @@ +{ + "kind": "SUM", + "flags": 0, + "description": "Queue Size change", + "monotonic": false, + "unit": "one", + "aggregationTemporality": "AGGREGATION_TEMPORALITY_CUMULATIVE", + "exemplars": [], + "name": "queueSizeChange", + "startTime": "2023-01-20T05:16:16.425669Z", + "@timestamp": "2023-01-20T05:16:16.425669Z", + "value.double": 0.0, + "resource": { + "cloud@account@id": "123367104812", + "process@pid": 1, + "host@arch": "amd64", + "host@id": "i-0005de88c8ebe7dbb", + "host@image@id": "ami-093d4bc1f6d4a890b", + "telemetry@sdk@version": "1.19.0", + "service@name": "AOCDockerDemoService", + "process@runtime@name": "OpenJDK Runtime Environment", + "os@type": "linux", + "cloud@availability_zone": "us-west-2b", + "host@type": "c5.2xlarge", + "cloud@provider": "aws", + "telemetry@sdk@language": "java", + "host@name": "ip-172-16-42-233.amazon.com", + "process@runtime@description": "Debian OpenJDK 64-Bit Server VM 17.0.4+8-Debian-1deb11u1", + "service@namespace": "AOCDockerDemo", + "cloud@region": "us-west-2", + "process@executable@path": "/usr/lib/jvm/java-17-openjdk-amd64/bin/java", + "process@command_line": "/usr/lib/jvm/java-17-openjdk-amd64/bin/java -javaagent:/aws-observability/classpath/aws-opentelemetry-agent-1.19.0-SNAPSHOT.jar", + "process@runtime@version": "17.0.4+8-Debian-1deb11u1", + "cloud@platform": "aws_ec2", + "telemetry@sdk@name": "opentelemetry", + "container@id": "71301ad845e7d082911d846ac9af3cd9ba4f2144d82d7ac0dfd51f335b256a61", + "telemetry@auto@version": "1.19.0-aws-SNAPSHOT", + "os@description": "Linux 5.4.225-139.416.amzn2int.x86_64" + }, + "instrumentationScope": { + "version": "1.0", + "name": "aws-otel", + "schemaUrl": "https://opentelemetry.io/schemas/1.13.0", + "attributes": { + "identification": "aws-ec2" + } + }, + + "attributes": { + "serviceName": "AOCDockerDemoService", + "statusCode": "", + "apiName": "", + "data_stream": { + "dataset": "sum", + "namespace": "production", + "type": "metric" + } + } +} diff --git a/src/main/resources/schema/observability/traces/README.md b/src/main/resources/schema/observability/traces/README.md new file mode 100644 index 000000000..dcf16adcb --- /dev/null +++ b/src/main/resources/schema/observability/traces/README.md @@ -0,0 +1,153 @@ +# Traces Schema Support +Observability in the software industry is the ability to monitor and diagnose systems and applications in real-time, in order to understand how they are behaving and identify potential issues. +Traces are a critical component of observability, providing detailed information about the flow of requests through a system, including timing information and any relevant contextual data. + +The importance of supporting traces schema lies in the fact that it enables better analysis and understanding of system behavior. +A structured schema provides a clear, consistent format for traces, making it easier for observability tools to process and aggregate the data. +This in turn makes it easier for engineers to understand the performance and behavior of their systems, and quickly identify potential issues. + +When traces are unstructured, it can be difficult for observability tools to extract meaningful information from them - For example, if the timing information for a particular request is not consistently represented in the same format, +it can be difficult to compare and analyze performance data over time. Similarly, if contextual data is not consistently recorded, it can be difficult to understand the context in which a particular request was executed. + +With a structured schema in place, observability tools can automatically extract and aggregate data, making it easier to understand system behavior at a high level. +This can help teams quickly identify performance bottlenecks, track the root cause of errors, and resolve issues more efficiently. + +## Details +The next section provides the Simple Schema for Observability support which conforms with the OTEL specification. + +- traces.mapping presents the template mapping for creating the Simple Schema for Observability index +- traces.schema presents the json schema validation for verification of a trace document conforms to the mapping structure + +### data-stream +[data-stream](https://opensearch.org/docs/latest/opensearch/data-streams/) Data streams simplify this process and enforce a setup that best suits time-series data, such as being designed primarily for append-only data and ensuring that each document has a timestamp field. +A data stream is internally composed of multiple backing indices. Search requests are routed to all the backing indices, while indexing requests are routed to the latest write index. + +As part of the Observability naming scheme, the value of the data stream fields combine to the name of the actual data stream : + +`{data_stream.type}-{data_stream.dataset}-{data_stream.namespace}`. +This means the fields can only contain characters that are valid as part of names of data streams. + +- **type** conforms to one of the supported Observability signals (Traces, Logs, Metrics, Alerts) +- **dataset** user defined field that can mainly be utilized for describing the origin of the signal +- **namespace** user custom field that can be used to describe any customer domain specific classification + +#### Timestamp field +As part of the data-stream definition the `@timestamp` is mandatory, if the field is not present to begin with use `ObservedTimestamp` as value for this field +**Note** - `@timestamp` value is the actual signal happening time and `observedTimestamp` is the time the exporter reads the actual event record. + +### Instrumentation scope +This is a logical unit of the application with which the emitted telemetry can be associated. It is typically the developer’s choice to decide what denotes a reasonable instrumentation scope. +The most common approach is to use the instrumentation library as the scope, however other scopes are also common, e.g. a module, a package, or a class can be chosen as the instrumentation scope. + +The instrumentation scope may have zero or more additional attributes that provide additional information about the scope. As an example the field +`instrumentationScope.attributes.identification` is presented will be used to determine the resource origin of the signal and can be used to filter accordingly + +## Traces +see [OTEL traces convention](https://github.com/open-telemetry/opentelemetry-specification/tree/main/semantic_conventions/trace) + +Traces are defined implicitly by their Spans - In particular, a Trace can be thought of as a directed acyclic graph (DAG) of Spans, where the edges between Spans are defined as parent/child relationship. + +## Spans +A span represents an operation within a transaction. Each Span encapsulates the following state: +Observability in the software industry is the ability to monitor and diagnose systems and applications in real-time, in order to understand how they are behaving and identify potential issues. +Traces are a critical component of observability, providing detailed information about the flow of requests through a system, including timing information and any relevant contextual data. + +The importance of supporting traces schema lies in the fact that it enables better analysis and understanding of system behavior. +A structured schema provides a clear, consistent format for traces, making it easier for observability tools to process and aggregate the data. +This in turn makes it easier for engineers to understand the performance and behavior of their systems, and quickly identify potential issues. + +When traces are unstructured, it can be difficult for observability tools to extract meaningful information from them - For example, if the timing information for a particular request is not consistently represented in the same format, +it can be difficult to compare and analyze performance data over time. Similarly, if contextual data is not consistently recorded, it can be difficult to understand the context in which a particular request was executed. + +With a structured schema in place, observability tools can automatically extract and aggregate data, making it easier to understand system behavior at a high level. +This can help teams quickly identify performance bottlenecks, track the root cause of errors, and resolve issues more efficiently. + +## Details +The next section provides the Simple Schema for Observability support which conforms with the OTEL specification. + +- traces.mapping presents the template mapping for creating the Simple Schema for Observability index +- traces.schema presents the json schema validation for verification of a trace document conforms to the mapping structure + +### data-stream +[data-stream](https://opensearch.org/docs/latest/opensearch/data-streams/) Data streams simplify this process and enforce a setup that best suits time-series data, such as being designed primarily for append-only data and ensuring that each document has a timestamp field. +A data stream is internally composed of multiple backing indices. Search requests are routed to all the backing indices, while indexing requests are routed to the latest write index. + +As part of the Observability naming scheme, the value of the data stream fields combine to the name of the actual data stream : + +`{data_stream.type}-{data_stream.dataset}-{data_stream.namespace}`. +This means the fields can only contain characters that are valid as part of names of data streams. + +- **type** conforms to one of the supported Observability signals (Traces, Logs, Metrics, Alerts) +- **dataset** user defined field that can mainly be utilized for describing the origin of the signal +- **namespace** user custom field that can be used to describe any customer domain specific classification + +#### Timestamp field +As part of the data-stream definition the `@timestamp` is mandatory, if the field is not present to begin with use `ObservedTimestamp` as value for this field +**Note** - `@timestamp` value is the actual signal happening time and `observedTimestamp` is the time the exporter reads the actual event record. + +### Instrumentation scope +This is a logical unit of the application with which the emitted telemetry can be associated. It is typically the developer’s choice to decide what denotes a reasonable instrumentation scope. +The most common approach is to use the instrumentation library as the scope, however other scopes are also common, e.g. a module, a package, or a class can be chosen as the instrumentation scope. + +The instrumentation scope may have zero or more additional attributes that provide additional information about the scope. As an example the field +`instrumentationScope.attributes.identification` is presented will be used to determine the resource origin of the signal and can be used to filter accordingly + +## Traces +see [OTEL traces convention](https://github.com/open-telemetry/opentelemetry-specification/tree/main/semantic_conventions/trace) + +Traces are defined implicitly by their Spans - In particular, a Trace can be thought of as a directed acyclic graph (DAG) of Spans, where the edges between Spans are defined as parent/child relationship. + +## Spans +A span represents an operation within a transaction. Each Span encapsulates the following state: + +* An operation name +* start and finish timestamp +* Attributes list of key-value pairs. +* Set of Events, each of which is itself a tuple (timestamp, name, Attributes) +* Parent's Span identifier. +* Links to causally-related Spans (via the SpanContext of those related Spans). +* SpanContext information required to reference a Span. + +### SpanContext +Represents all the information that identifies Span in the Trace and is propagated to child Spans and across process boundaries. +A **SpanContext** contains the tracing identifiers and the options that are propagated from parent to child Spans. + +* `TraceId` - It is worldwide unique with practically sufficient probability by being made as 16 randomly generated bytes - used to group all spans for a specific trace together across all processes. +* `SpanId` - It is the identifier for a span, globally unique with practically sufficient probability by being made as 8 randomly generated bytes. When passed to a child Span this identifier becomes the parent span id for the child Span. +* `Tracestate` - carries tracing-system specific context in a list of key value pairs . Trace-state allows different vendors propagate additional information and inter-operate with their legacy Id formats. For more details see this. + +Additional fields can be supported via the Attributes key/value store see [traces](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/README.md) + +### Structure +The default fields that are supported by the traces are +- **TraceId** : It is worldwide unique with practically sufficient probability by being made as 16 randomly generated bytes - used to group all spans for a specific trace together across all processes. +- **SpanId** : It is the identifier for a span, globally unique with practically sufficient probability by being made as 8 randomly generated bytes. When passed to a child Span this identifier becomes the parent span id for the child Span. +- **ParentId** : It is the identifier for a span's parent span. +- **TraceState** : carries tracing-system specific context in a list of key value pairs. Tracestate allows different vendors propagate additional information and inter-operate with their legacy Id formats. + +- **Name** : String representing the span's name +- **Kind** + - SpanKind.CLIENT + - SpanKind.SERVER + - SpanKind.CONSUMER + - SpanKind.PRODUCER + - SpanKind.INTERNAL + +- **StartTime** : Start time of the event +- **EndTime** : End time of the event +- **Attributes** + - An Attribute is a key-value pair, which has the following structure [Attributes](https://github.com/open-telemetry/opentelemetry-specification/blob/b00980832b4b823155001df56dbf9203d4e53f98/specification/common/README.md#attribute) + +- **DroppedAttributesCount** : Integer counting the dropped attributes +- **Events** : A set of the next tuples (timestamp, name, Attributes) +- **DroppedEventsCount** : Integer counting the dropped events +- **Links** : links to causally-related Spans +- **DroppedLinksCount** : Integer counting the dropped links +- **Status** - + + _status code is the int value + status message is the text representation_ + + - `UNSET = 0` : The default status. + - `OK = 1` : The operation has been validated by an Application developer or Operator to have completed successfully. + - `ERROR = 2` : The operation contains an error. \ No newline at end of file diff --git a/src/main/resources/schema/observability/traces/samples/load_samples.md b/src/main/resources/schema/observability/traces/samples/load_samples.md new file mode 100644 index 000000000..9536522c3 --- /dev/null +++ b/src/main/resources/schema/observability/traces/samples/load_samples.md @@ -0,0 +1,28 @@ +## Load samples +For loading the given samples run the next request once the Opensearch cluster including Observability plugin has started: + + +`PUT sso_traces-default-namespace/_bulk` +```json +{ "create":{ } } +{"traceId":"4fa04f117be100f476b175e41096e736","spanId":"e275ac9d21929e9b","traceState":[],"parentSpanId":"","name":"client_checkout","kind":"INTERNAL","@timestamp":"2021-11-13T20:20:39+00:00","endTime":"2021-11-14T20:10:41+00:00","droppedAttributesCount":0,"droppedEventsCount":0,"droppedLinksCount":0,"resource":{"telemetry@sdk@name":"opentelemetry","telemetry@sdk@language":"python","telemetry@sdk@version":"0.14b0","service@name":"frontend-client","host@hostname":"ip-172-31-10-8.us-west-2.compute.internal"},"status":{"code":0}} +{ "create":{ } } +{"traceId":"15d30e4d211d79e10fcaeab97015c90d","spanId":"5bcca8ba513bb54a","traceState":[],"parentSpanId":"","name":"mysql","kind":"CLIENT","@timestamp":"2021-11-13T20:20:39+00:00","endTime":"2021-11-14T20:10:41+00:00","events":[{"@timestamp":"2021-03-25T17:21:03.044+00:00","name":"exception","attributes":{"exception@message":"1050 %2842S01%29: Table %27User_Carts%27 already exists","exception@type":"ProgrammingError","exception@stacktrace":"Traceback %28most recent call last :File /usr/lib/python3.6/site-packages/opentelemetry/sdk/trace/__init__.py, line 804, in use_span yield spanFile /usr/lib/python3.6/site-packages/opentelemetry/instrumentation/dbapi/__init__.py, line 354, in traced_executionraise exFile /usr/lib/python3.6/site-packages/opentelemetry/instrumentation/dbapi/__init__.py, line 345, in traced_executionresult = query_method%28%2Aargs, %2A%2Akwargs%29File /usr/lib/python3.6/site-packages/mysql/connector/cursor.py"},"droppedAttributesCount":0}],"links":[],"droppedAttributesCount":0,"droppedEventsCount":0,"droppedLinksCount":0,"status":{"message":"1050 %2842S01%29: Table %27User_Carts%27 already exists","code":2},"attributes":{"data_stream":{"type":"span","dataset":"mysql"},"component":"mysql","db@user":"root","net@peer@name":"localhost","db@type":"sql","net@peer@port":3306,"db@instance":"","db@statement":"CREATE TABLE `User_Carts` %28 `ItemId` varchar%2816%29 NOT NULL, `TotalQty` int%2811%29 NOT NULL, PRIMARY KEY %28`ItemId`%29%29 ENGINE=InnoDB"},"resource":{"telemetry@sdk@language":"python","service@name":"database","telemetry@sdk@version":"0.14b0","service@instance@id":"140307275923408","telemetry@sdk@name":"opentelemetry","host@hostname":"ip-172-31-10-8.us-west-2.compute.internal"}} +{ "create":{ } } +{"traceId":"c1d985bd02e1dbb85b444011f19a1ecc","spanId":"55a698828fe06a42","traceState":[],"parentSpanId":"","name":"mysql","kind":"CLIENT","@timestamp":"2021-11-13T20:20:39+00:00","endTime":"2021-11-14T20:10:41+00:00","events":[{"@timestamp":"2021-03-25T17:21:03+00:00","name":"exception","attributes":{"exception@message":"1050 %2842S01%29: Table Inventory_Items already exists","exception@type":"ProgrammingError","exception@stacktrace":"Traceback most recent call last"},"droppedAttributesCount":0}],"links":[{"traceId":"c1d985bd02e1dbb85b444011f19a1ecc","spanId":"55a698828fe06a42w2","traceState":[],"attributes":{"db@user":"root","net@peer@name":"localhost","component":"mysql","db@type":"sql","net@peer@port":3306,"db@instance":"","db@statement":"CREATE TABLE `Inventory_Items` %28 `ItemId` varchar%2816%29 NOT NULL, `TotalQty` int%2811%29 NOT NULL, PRIMARY KEY %28`ItemId`%29%29 ENGINE=InnoDB"},"droppedAttributesCount":0}],"droppedAttributesCount":0,"droppedEventsCount":0,"droppedLinksCount":0,"resource":{"telemetry@sdk@language":"python","telemetry@sdk@version":"0.14b0","service@instance@id":"140307275923408","service@name":"database","telemetry@sdk@name":"opentelemetry","host@hostname":"ip-172-31-10-8.us-west-2.compute.internal"},"status":{"code":2,"message":"1050 %2842S01%29: Table %27Inventory_Items%27 already exists"},"attributes":{"data_stream":{"type":"span","namespace":"exceptions","dataset":"mysql"},"db@user":"root","net@peer@name":"localhost","component":"mysql","db@type":"sql","net@peer@port":3306,"db@instance":"","db@statement":"CREATE TABLE `Inventory_Items` %28 `ItemId` varchar%2816%29 NOT NULL, `TotalQty` int%2811%29 NOT NULL, PRIMARY KEY %28`ItemId`%29%29 ENGINE=InnoDB"}} +``` + +Run the next query to get the Spans kind CLIENT: + +- `GET sso_traces-default-namespace/_search` +```json +{ + "query":{ + "term": { + "kind":{ + "value":"CLIENT" + } + } + } +} +``` \ No newline at end of file diff --git a/src/main/resources/schema/observability/traces/samples/traceA.json b/src/main/resources/schema/observability/traces/samples/traceA.json new file mode 100644 index 000000000..451ae8249 --- /dev/null +++ b/src/main/resources/schema/observability/traces/samples/traceA.json @@ -0,0 +1,23 @@ +{ + "traceId": "4fa04f117be100f476b175e41096e736", + "spanId": "e275ac9d21929e9b", + "traceState": [], + "parentSpanId": "", + "name": "client_checkout", + "kind": "INTERNAL", + "@timestamp": "2021-11-13T20:20:39+00:00", + "endTime": "2021-11-14T20:10:41+00:00", + "droppedAttributesCount": 0, + "droppedEventsCount": 0, + "droppedLinksCount": 0, + "resource": { + "telemetry@sdk@name": "opentelemetry", + "telemetry@sdk@language": "python", + "telemetry@sdk@version": "0.14b0", + "service@name": "frontend-client", + "host@hostname": "ip-172-31-10-8.us-west-2.compute.internal" + }, + "status": { + "code": 0 + } +} \ No newline at end of file diff --git a/src/main/resources/schema/observability/traces/samples/traceB.json b/src/main/resources/schema/observability/traces/samples/traceB.json new file mode 100644 index 000000000..cf5ab4979 --- /dev/null +++ b/src/main/resources/schema/observability/traces/samples/traceB.json @@ -0,0 +1,51 @@ +{ + "traceId": "15d30e4d211d79e10fcaeab97015c90d", + "spanId": "5bcca8ba513bb54a", + "traceState": [], + "parentSpanId": "", + "name": "mysql", + "kind": "CLIENT", + "@timestamp": "2021-11-13T20:20:39+00:00", + "endTime": "2021-11-14T20:10:41+00:00", + "events": [ + { + "@timestamp": "2021-03-25T17:21:03.044+00:00", + "name": "exception", + "attributes": { + "exception@message": "1050 %2842S01%29: Table %27User_Carts%27 already exists", + "exception@type": "ProgrammingError", + "exception@stacktrace": "Traceback %28most recent call last :File /usr/lib/python3.6/site-packages/opentelemetry/sdk/trace/__init__.py, line 804, in use_span yield spanFile /usr/lib/python3.6/site-packages/opentelemetry/instrumentation/dbapi/__init__.py, line 354, in traced_executionraise exFile /usr/lib/python3.6/site-packages/opentelemetry/instrumentation/dbapi/__init__.py, line 345, in traced_executionresult = query_method%28%2Aargs, %2A%2Akwargs%29File /usr/lib/python3.6/site-packages/mysql/connector/cursor.py" + }, + "droppedAttributesCount": 0 + } + ], + "links": [], + "droppedAttributesCount": 0, + "droppedEventsCount": 0, + "droppedLinksCount": 0, + "status": { + "message": "1050 %2842S01%29: Table %27User_Carts%27 already exists", + "code": 2 + }, + "attributes": { + "data_stream": { + "type": "span", + "dataset": "mysql" + }, + "component": "mysql", + "db@user": "root", + "net@peer@name": "localhost", + "db@type": "sql", + "net@peer@port": 3306, + "db@instance": "", + "db@statement": "CREATE TABLE `User_Carts` %28 `ItemId` varchar%2816%29 NOT NULL, `TotalQty` int%2811%29 NOT NULL, PRIMARY KEY %28`ItemId`%29%29 ENGINE=InnoDB" + }, + "resource": { + "telemetry@sdk@language": "python", + "service@name": "database", + "telemetry@sdk@version": "0.14b0", + "service@instance@id": "140307275923408", + "telemetry@sdk@name": "opentelemetry", + "host@hostname": "ip-172-31-10-8.us-west-2.compute.internal" + } +} \ No newline at end of file diff --git a/src/main/resources/schema/observability/traces/samples/traceC.json b/src/main/resources/schema/observability/traces/samples/traceC.json new file mode 100644 index 000000000..7da4fd7a7 --- /dev/null +++ b/src/main/resources/schema/observability/traces/samples/traceC.json @@ -0,0 +1,68 @@ +{ + "traceId": "c1d985bd02e1dbb85b444011f19a1ecc", + "spanId": "55a698828fe06a42", + "traceState": [], + "parentSpanId": "", + "name": "mysql", + "kind": "CLIENT", + "@timestamp": "2021-11-13T20:20:39+00:00", + "endTime": "2021-11-14T20:10:41+00:00", + "events": [ + { + "@timestamp": "2021-03-25T17:21:03+00:00", + "name": "exception", + "attributes": { + "exception@message": "1050 %2842S01%29: Table Inventory_Items already exists", + "exception@type": "ProgrammingError", + "exception@stacktrace": "Traceback most recent call last" + }, + "droppedAttributesCount": 0 + } + ], + "links": [ + { + "traceId": "c1d985bd02e1dbb85b444011f19a1ecc", + "spanId": "55a698828fe06a42w2", + "traceState": [], + "attributes": { + "db@user": "root", + "net@peer@name": "localhost", + "component": "mysql", + "db@type": "sql", + "net@peer@port": 3306, + "db@instance": "", + "db@statement": "CREATE TABLE `Inventory_Items` %28 `ItemId` varchar%2816%29 NOT NULL, `TotalQty` int%2811%29 NOT NULL, PRIMARY KEY %28`ItemId`%29%29 ENGINE=InnoDB" + }, + "droppedAttributesCount": 0 + } + ], + "droppedAttributesCount": 0, + "droppedEventsCount": 0, + "droppedLinksCount": 0, + "resource": { + "telemetry@sdk@language": "python", + "telemetry@sdk@version": "0.14b0", + "service@instance@id": "140307275923408", + "service@name": "database", + "telemetry@sdk@name": "opentelemetry", + "host@hostname": "ip-172-31-10-8.us-west-2.compute.internal" + }, + "status": { + "code": 2, + "message": "1050 %2842S01%29: Table %27Inventory_Items%27 already exists" + }, + "attributes": { + "data_stream": { + "type": "span", + "namespace": "exceptions", + "dataset": "mysql" + }, + "db@user": "root", + "net@peer@name": "localhost", + "component": "mysql", + "db@type": "sql", + "net@peer@port": 3306, + "db@instance": "", + "db@statement": "CREATE TABLE `Inventory_Items` %28 `ItemId` varchar%2816%29 NOT NULL, `TotalQty` int%2811%29 NOT NULL, PRIMARY KEY %28`ItemId`%29%29 ENGINE=InnoDB" + } +} diff --git a/src/main/resources/schema/observability/traces/services.mapping b/src/main/resources/schema/observability/traces/services.mapping new file mode 100644 index 000000000..06b9ab681 --- /dev/null +++ b/src/main/resources/schema/observability/traces/services.mapping @@ -0,0 +1,65 @@ +{ + "template": { + "mappings": { + "mappings": { + "dynamic_templates": [ + { + "strings_as_keyword": { + "match_mapping_type": "string", + "mapping": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + ], + "date_detection": false, + "properties": { + "services": { + "destination": { + "properties": { + "domain": { + "type": "keyword", + "ignore_above": 1024 + }, + "resource": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "hashId": { + "type": "keyword", + "ignore_above": 1024 + }, + "kind": { + "type": "keyword", + "ignore_above": 1024 + }, + "serviceName": { + "type": "keyword", + "ignore_above": 1024 + }, + "target": { + "properties": { + "domain": { + "type": "keyword", + "ignore_above": 1024 + }, + "resource": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "traceGroupName": { + "type": "keyword", + "ignore_above": 1024 + } + } + } + } + } + } +} +} \ No newline at end of file diff --git a/src/main/resources/schema/observability/traces/traces.mapping b/src/main/resources/schema/observability/traces/traces.mapping new file mode 100644 index 000000000..a6be2931f --- /dev/null +++ b/src/main/resources/schema/observability/traces/traces.mapping @@ -0,0 +1,200 @@ +{ + "index_patterns": [ + "sso_traces-*-*" + ], + "data_stream": {}, + "template": { + "mappings": { + "_meta": { + "version": "1.0.0" + }, + "dynamic_templates": [ + { + "attributes_map": { + "mapping": { + "type": "keyword" + }, + "path_match": "attributes.*" + } + }, + { + "events_attributes_map": { + "mapping": { + "type": "keyword" + }, + "path_match": "events.attributes.*" + } + }, + { + "links_attributes_map": { + "mapping": { + "type": "keyword" + }, + "path_match": "links.attributes.*" + } + }, + { + "instrumentation_scope_attributes_map": { + "mapping": { + "type": "keyword" + }, + "path_match": "instrumentationScope.attributes.*" + } + }, + { + "resources_map": { + "mapping": { + "type": "keyword" + }, + "path_match": "resource.*" + } + } + ], + "_source": { + "enabled": true + }, + "properties": { + "traceId": { + "ignore_above": 256, + "type": "keyword" + }, + "spanId": { + "ignore_above": 256, + "type": "keyword" + }, + "traceState": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "parentSpanId": { + "ignore_above": 256, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "kind": { + "ignore_above": 128, + "type": "keyword" + }, + "startTime": { + "type": "date_nanos" + }, + "endTime": { + "type": "date_nanos" + }, + "droppedAttributesCount": { + "type": "long" + }, + "droppedEventsCount": { + "type": "long" + }, + "droppedLinksCount": { + "type": "long" + }, + "status": { + "properties": { + "code": { + "type": "long" + }, + "message": { + "ignore_above": 128, + "type": "keyword" + } + } + }, + "attributes": { + "type": "object", + "properties": { + "data_stream": { + "properties": { + "dataset": { + "ignore_above": 128, + "type": "keyword" + }, + "namespace": { + "ignore_above": 128, + "type": "keyword" + }, + "type": { + "ignore_above": 56, + "type": "keyword" + } + } + } + } + }, + "events": { + "type": "nested", + "properties": { + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "@timestamp": { + "type": "date_nanos" + }, + "observedTimestamp": { + "type": "date_nanos" + } + } + }, + "links": { + "type": "nested", + "properties": { + "traceId": { + "ignore_above": 256, + "type": "keyword" + }, + "spanId": { + "ignore_above": 256, + "type": "keyword" + }, + "traceState": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + } + } + }, + "instrumentationScope": { + "properties": { + "name": { + "type": "keyword" + }, + "version": { + "type": "keyword" + }, + "droppedAttributesCount": { + "type": "integer" + }, + "schemaUrl": { + "type": "keyword" + } + } + }, + "schemaUrl": { + "type": "keyword" + } + } + } + }, + "composed_of": [ + ], + "version": 1, + "_meta": { + "description": "Observability Traces Mapping Template", + "catalog": "observability", + "type": "traces" + } +} \ No newline at end of file diff --git a/src/main/resources/schema/observability/traces/traces.schema b/src/main/resources/schema/observability/traces/traces.schema new file mode 100644 index 000000000..6225c0ed4 --- /dev/null +++ b/src/main/resources/schema/observability/traces/traces.schema @@ -0,0 +1,249 @@ +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "$id": "https://opensearch.org/schemas/Span", + "type": "object", + "additionalProperties": false, + "properties": { + "traceId": { + "type": "string" + }, + "spanId": { + "type": "string" + }, + "traceState": { + "type": "array", + "items": { + "$ref": "#/definitions/KeyValue" + } + }, + "status": { + "type": "object", + "$ref": "#/definitions/Status" + }, + "parentSpanId": { + "type": "string" + }, + "name": { + "type": "string" + }, + "kind": { + "type": "string", + "items": { + "type": "string", + "enum": [ + "SPAN_KIND_UNSPECIFIED", + "SPAN_KIND_INTERNAL", + "SPAN_KIND_SERVER", + "SPAN_KIND_CLIENT", + "SPAN_KIND_PRODUCER", + "SPAN_KIND_CONSUMER" + ] + } + }, + "startTime": { + "type": "string", + "format": "date-time" + }, + "endTime": { + "type": "string", + "format": "date-time" + }, + "resource": { + "type": "object" + }, + "attributes": { + "$ref": "#/definitions/Attributes" + }, + "events": { + "type": "array", + "items": { + "$ref": "#/definitions/Event" + } + }, + "links": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "traceId": { + "type": "string" + }, + "spanId": { + "type": "string" + }, + "traceState": { + "type": "array", + "items": { + "type": "object" + } + }, + "attributes": { + "$ref": "#/definitions/Attributes" + }, + "droppedAttributesCount": { + "type": "integer" + } + }, + "required": [ + "traceId", + "spanId", + "traceState" + ], + "title": "Links" + } + }, + "droppedAttributesCount": { + "type": "integer" + }, + "droppedEventsCount": { + "type": "integer" + }, + "droppedLinksCount": { + "type": "integer" + }, + "instrumentationScope": { + "$ref": "#/definitions/InstrumentationScope" + }, + "schemaUrl": { + "type": "string" + } + }, + "required": [ + "traceId", + "spanId", + "startTime", + "endTime", + "kind", + "name", + "status" + ], + "definitions": { + "Status": { + "$id": "#/definitions/Status", + "type": "object", + "additionalProperties": false, + "properties": { + "code": { + "type": "integer", + "items": { + "type": "integer", + "enum": [ + 0, + 1, + 2 + ] + } + }, + "message": { + "type": "string", + "items": { + "type": "string", + "enum": [ + "UNSET", + "OK", + "ERROR" + ] + } + } + }, + "required": [ + "code" + ], + "title": "Status" + }, + "Event": { + "$id": "#/definitions/Event", + "type": "object", + "additionalProperties": false, + "properties": { + "@timestamp": { + "type": "string", + "format": "date-time" + }, + "observedTimestamp": { + "type": "string", + "format": "date-time" + }, + "name": { + "type": "string" + }, + "attributes": { + "$ref": "#/definitions/Attributes" + }, + "droppedAttributesCount": { + "type": "integer" + } + }, + "required": [ + "attributes", + "droppedAttributesCount", + "name", + "@timestamp" + ], + "title": "Event" + }, + "Attributes": { + "$id": "#/definitions/Attributes", + "type": "object", + "additionalProperties": true, + "properties": { + "data_stream": { + "$ref": "#/definitions/Dataflow" + } + }, + "title": "Attributes" + }, + "KeyValue": { + "$id": "#/definitions/KeyValue", + "type": "object", + "additionalProperties": true, + "properties": { + "key": { + "type": "string" + }, + "value": { + "type": "object" + } + }, + "title": "KeyValue" + }, + "InstrumentationScope": { + "$id": "#/definitions/InstrumentationScope", + "type": "object", + "additionalProperties": true, + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "schemaUrl": { + "type": "string" + }, + "droppedAttributesCount": { + "type": "integer" + } + }, + "title": "InstrumentationScope" + }, + "Dataflow": { + "$id": "#/definitions/Dataflow", + "type": "object", + "additionalProperties": true, + "properties": { + "type": { + "type": "string" + }, + "namespace": { + "type": "string" + }, + "dataset": { + "type": "string" + } + }, + "title": "Attributes" + } + } +} diff --git a/src/main/resources/schema/security/README.md b/src/main/resources/schema/security/README.md new file mode 100644 index 000000000..1695a2edc --- /dev/null +++ b/src/main/resources/schema/security/README.md @@ -0,0 +1,3 @@ +# Security Domain Schema + +OpenSearch Security is a [plugin](https://github.com/opensearch-project/security) for OpenSearch that offers encryption, authentication and authorization. When combined with OpenSearch Security-Advanced Modules, it supports authentication via Active Directory, LDAP, Kerberos, JSON web tokens, SAML, OpenID and more. It includes fine grained role-based access control to indices, documents and fields. It also provides multi-tenancy support in OpenSearch Dashboards. diff --git a/src/main/resources/schema/system/README.md b/src/main/resources/schema/system/README.md new file mode 100644 index 000000000..bad8cabc7 --- /dev/null +++ b/src/main/resources/schema/system/README.md @@ -0,0 +1,65 @@ +# Internal System Schema + +This folder contains internal representation of assets that are stored in the system indices of dashboard and integration. + - Application + - Datasource + - Index-Pattern + - Integration + - Notebook + - Operational-Panel + - SavedQuery + - Visualization + +### Application +[Application](https://opensearch.org/docs/2.5/observing-your-data/app-analytics/) enables creation of custom observability display to view the availability status of your systems, where you can combine log events with trace and metric data into a single view of overall system health. +This lets you quickly pivot between logs, traces, and metrics to dig into the source of any issues. + + - [Schema](application.schema) + - [Sample](samples/application.json) + +### Datasource +[Data-source](https://opensearch.org/docs/2.4/dashboards/discover/multi-data-sources/) Enables adding multiple data sources to a single dashboard. +OpenSearch Dashboards allows you to dynamically manage data sources, create index patterns based on those data sources, and execute queries against a specific data source and then combine visualizations in one dashboard. + + - [Schema](datasource.schema) + - [Sample](samples/datasource.json) + +### Index-Pattern +An Index Pattern allows to access data that you want to explore. An index pattern selects the data to use. An index pattern may point to multiple indices, data stream, or index aliases. + + - [Schema](index-pattern.schema) + - [Sample](samples/index-pattern.json) + +### Integration +Integration is a schematized and categorized bundle of assets grouped together to allow simple and coherent way to view, analyze and investigate different aspects of your data. +Integrations allow pre-defining dashboards, visualizations, index-templates, saved-queries and additional assets so that they provide a complete meaningful user experience. + + - [Schema](integration.schema) + - [Sample](samples/integration.json) + +### Notebook +[Notebook](https://opensearch.org/docs/2.5/observing-your-data/notebooks/) A notebook is a document composed of two elements: code blocks (Markdown/SQL/PPL) and visualizations. +Choose multiple timelines to compare and contrast visualizations. +You can also generate reports directly from your notebooks. Common use cases include creating postmortem reports, designing runbooks, building live infrastructure reports, and writing documentation. + + - [Schema](notebook.schema) + - [Sample](samples/notebook.json) + +### Operational-Panel +[Operational Panels](https://opensearch.org/docs/2.5/observing-your-data/operational-panels/) in OpenSearch Dashboards are collections of visualizations generated using Piped Processing Language (PPL) queries. + + - [Schema](operational-panel.schema) + - [Sample](samples/operationalPanel.json) + +### Saved-Query +A saved query (saved search) allows to reuse a search created in a dashboard for other dashboards. + + - [Schema](saved-query.schema) + - [Sample](samples/savedQuery.json) + +### Visualization +[Visualization](https://opensearch.org/docs/2.5/dashboards/visualize/viz-index/) allows translation of complex, high-volume, or numerical data into a visual representation that is easier to process. +OpenSearch Dashboards gives you data visualization tools to improve and automate the visual communication process. By using visual elements like charts, graphs, or maps to represent data, you can advance business intelligence and support data-driven decision-making and strategic planning. + + - [Schema](visualization.schema) + - [Sample](samples/visualization.json) diff --git a/src/main/resources/schema/system/application.schema b/src/main/resources/schema/system/application.schema new file mode 100644 index 000000000..2bf2ec686 --- /dev/null +++ b/src/main/resources/schema/system/application.schema @@ -0,0 +1,49 @@ +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "$ref": "#/definitions/Application", + "definitions": { + "Application": { + "type": "object", + "additionalProperties": false, + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "baseQuery": { + "type": "string" + }, + "servicesEntities": { + "type": "array", + "items": { + "type": "string" + } + }, + "traceGroups": { + "type": "array", + "items": { + "type": "string" + } + }, + "panelId": { + "type": "string" + }, + "availabilityVisId": { + "type": "string" + } + }, + "required": [ + "availabilityVisId", + "baseQuery", + "description", + "name", + "panelId", + "servicesEntities", + "traceGroups" + ], + "title": "Application" + } + } +} diff --git a/src/main/resources/schema/system/catalog.schema b/src/main/resources/schema/system/catalog.schema new file mode 100644 index 000000000..2c8a8c7f9 --- /dev/null +++ b/src/main/resources/schema/system/catalog.schema @@ -0,0 +1,104 @@ +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "$ref": "#/definitions/Catalog", + "definitions": { + "Catalog": { + "type": "object", + "additionalProperties": false, + "properties": { + "catalog": { + "type": "string" + }, + "version": { + "type": "string" + }, + "url": { + "type": "string", + "format": "uri", + "qt-uri-protocols": [ + "https" + ] + }, + "categories": { + "type": "array", + "items": { + "$ref": "#/definitions/Category" + } + } + }, + "required": [ + "catalog", + "categories", + "url", + "version" + ], + "title": "Catalog" + }, + "Category": { + "type": "object", + "additionalProperties": false, + "properties": { + "category": { + "type": "string" + }, + "version": { + "type": "string" + }, + "url": { + "type": "string", + "format": "uri", + "qt-uri-protocols": [ + "https" + ] + }, + "components": { + "type": "array", + "items": { + "$ref": "#/definitions/Component" + } + } + }, + "required": [ + "category", + "components", + "url", + "version" + ], + "title": "Category" + }, + "Component": { + "type": "object", + "additionalProperties": false, + "properties": { + "component": { + "type": "string" + }, + "version": { + "type": "string" + }, + "url": { + "type": "string", + "format": "uri", + "qt-uri-protocols": [ + "https" + ] + }, + "container": { + "type": "boolean" + }, + "tags": { + "type": "array", + "items": {} + } + }, + "required": [ + "component", + "container", + "tags", + "url", + "version" + ], + "title": "Component" + } + } +} diff --git a/src/main/resources/schema/system/datasource.schema b/src/main/resources/schema/system/datasource.schema new file mode 100644 index 000000000..7cf8be989 --- /dev/null +++ b/src/main/resources/schema/system/datasource.schema @@ -0,0 +1,69 @@ +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "$ref": "#/definitions/Datasource", + "definitions": { + "Datasource": { + "type": "object", + "additionalProperties": false, + "properties": { + "title": { + "type": "string" + }, + "description": { + "type": "string" + }, + "endpoint": { + "type": "string", + "format": "uri", + "qt-uri-protocols": [ + "http" + ] + }, + "auth": { + "$ref": "#/definitions/Auth" + } + }, + "required": [ + "auth", + "description", + "endpoint", + "title" + ], + "title": "Datasource" + }, + "Auth": { + "type": "object", + "additionalProperties": false, + "properties": { + "type": { + "type": "string" + }, + "credentials": { + "$ref": "#/definitions/Credentials" + } + }, + "required": [ + "credentials", + "type" + ], + "title": "Auth" + }, + "Credentials": { + "type": "object", + "additionalProperties": false, + "properties": { + "username": { + "type": "string" + }, + "password": { + "type": "string" + } + }, + "required": [ + "password", + "username" + ], + "title": "Credentials" + } + } +} diff --git a/src/main/resources/schema/system/index-pattern.schema b/src/main/resources/schema/system/index-pattern.schema new file mode 100644 index 000000000..9cce9cd52 --- /dev/null +++ b/src/main/resources/schema/system/index-pattern.schema @@ -0,0 +1,25 @@ +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "$ref": "#/definitions/IndexPattern", + "definitions": { + "IndexPattern": { + "type": "object", + "additionalProperties": false, + "properties": { + "title": { + "type": "string" + }, + "fields": { + "type": "string" + }, + "timeFieldName": { + "type": "string" + } + }, + "required": [ + "title" + ], + "title": "IndexPattern" + } + } +} diff --git a/src/main/resources/schema/system/integration-instance.schema b/src/main/resources/schema/system/integration-instance.schema new file mode 100644 index 000000000..959842e91 --- /dev/null +++ b/src/main/resources/schema/system/integration-instance.schema @@ -0,0 +1,87 @@ +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "$ref": "#/definitions/IntegrationInstance", + "definitions": { + "IntegrationInstance": { + "type": "object", + "additionalProperties": false, + "properties": { + "template-name": { + "type": "string" + }, + "namespace": { + "type": "string" + }, + "dataset": { + "type": "string" + }, + "id": { + "type": "string" + }, + "version": { + "type": "string" + }, + "description": { + "type": "string" + }, + "template": { + "type": "string", + "format": "uri", + "qt-uri-protocols": [ + "https" + ], + "qt-uri-extensions": [ + ".json" + ] + }, + "creationDate": { + "type": "string", + "format": "date-time" + }, + "status": { + "type": "string" + }, + "assets": { + "type": "array", + "items": { + "$ref": "#/definitions/Asset" + } + } + }, + "required": [ + "assets", + "creationDate", + "description", + "dataset", + "id", + "template-name", + "namespace", + "status", + "template", + "version" + ], + "title": "IntegrationInstance" + }, + "Asset": { + "type": "object", + "additionalProperties": false, + "properties": { + "name": { + "type": "string" + }, + "creationDate": { + "type": "string" + }, + "status": { + "type": "string" + } + }, + "required": [ + "creationDate", + "name", + "status" + ], + "title": "Asset" + } + } +} diff --git a/src/main/resources/schema/system/integration.schema b/src/main/resources/schema/system/integration.schema new file mode 100644 index 000000000..481b9f516 --- /dev/null +++ b/src/main/resources/schema/system/integration.schema @@ -0,0 +1,176 @@ +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "$ref": "#/definitions/Integration", + "definitions": { + "Integration": { + "type": "object", + "additionalProperties": false, + "properties": { + "template-name": { + "type": "string" + }, + "version": { + "$ref": "#/definitions/Version" + }, + "description": { + "type": "string" + }, + "catalog": { + "type": "string" + }, + "identification": { + "type": "string" + }, + "components": { + "type": "array", + "items": { + "type": "string" + } + }, + "collection": { + "type": "array", + "items": { + "$ref": "#/definitions/Collection" + } + }, + "repository": { + "$ref": "#/definitions/repository" + } + }, + "required": [ + "catalog", + "components", + "collection", + "description", + "identification", + "template-name", + "repository", + "version" + ], + "title": "Integration" + }, + "Collection": { + "type": "object", + "additionalProperties": false, + "properties": { + "logs": { + "type": "array", + "items": { + "$ref": "#/definitions/Log" + } + }, + "metrics": { + "type": "array", + "items": { + "$ref": "#/definitions/Log" + } + } + }, + "required": [], + "title": "Collection" + }, + "Log": { + "type": "object", + "additionalProperties": false, + "properties": { + "info": { + "type": "string" + }, + "input_type": { + "type": "string" + }, + "dataset": { + "type": "string" + }, + "labels": { + "type": "array", + "items": { + "type": "string" + } + }, + "schema": { + "type": "string" + }, + "fields-mapping": { + "type": "array", + "items": [ + { + "type": "object", + "properties": { + "alias": { + "type": "string" + }, + "field": { + "type": "string" + } + }, + "required": [ + "alias", + "field" + ] + }, + { + "type": "object", + "properties": { + "alias": { + "type": "string" + }, + "field": { + "type": "string" + } + }, + "required": [ + "alias", + "field" + ] + } + ] + } + }, + "required": [ + "dataset", + "info", + "input_type", + "labels" + ], + "title": "Log" + }, + "repository": { + "type": "object", + "additionalProperties": false, + "properties": { + "url": { + "type": "string", + "format": "uri", + "qt-uri-protocols": [ + "https" + ] + } + }, + "required": [ + "url" + ], + "title": "repository" + }, + "Version": { + "type": "object", + "additionalProperties": false, + "properties": { + "integration": { + "type": "string" + }, + "schema": { + "type": "string" + }, + "resource": { + "type": "string" + } + }, + "required": [ + "integration", + "resource" + ], + "title": "Version" + } + } +} diff --git a/src/main/resources/schema/system/integrations-template-list.schema b/src/main/resources/schema/system/integrations-template-list.schema new file mode 100644 index 000000000..49e1e99ee --- /dev/null +++ b/src/main/resources/schema/system/integrations-template-list.schema @@ -0,0 +1,41 @@ +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "type": "array", + "items": { + "$ref": "#/definitions/IntegrationsTemplateList" + }, + "definitions": { + "IntegrationsTemplateList": { + "type": "object", + "additionalProperties": false, + "properties": { + "template-name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "description": { + "type": "string" + }, + "catalog": { + "type": "string" + }, + "collections": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "catalog", + "collections", + "description", + "template-name", + "version" + ], + "title": "IntegrationsTemplateList" + } + } +} diff --git a/src/main/resources/schema/system/notebook.schema b/src/main/resources/schema/system/notebook.schema new file mode 100644 index 000000000..da6891bdf --- /dev/null +++ b/src/main/resources/schema/system/notebook.schema @@ -0,0 +1,112 @@ +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "$ref": "#/definitions/Notebook", + "definitions": { + "Notebook": { + "type": "object", + "additionalProperties": false, + "properties": { + "dateCreated": { + "type": "string", + "format": "date-time" + }, + "name": { + "type": "string" + }, + "dateModified": { + "type": "string", + "format": "date-time" + }, + "backend": { + "type": "string" + }, + "paragraphs": { + "type": "array", + "items": { + "$ref": "#/definitions/Paragraph" + } + } + }, + "required": [ + "backend", + "dateCreated", + "dateModified", + "name", + "paragraphs" + ], + "title": "Notebook" + }, + "Paragraph": { + "type": "object", + "additionalProperties": false, + "properties": { + "output": { + "type": "array", + "items": { + "$ref": "#/definitions/Output" + } + }, + "input": { + "$ref": "#/definitions/Input" + }, + "dateCreated": { + "type": "string", + "format": "date-time" + }, + "dateModified": { + "type": "string", + "format": "date-time" + }, + "id": { + "type": "string" + } + }, + "required": [ + "dateCreated", + "dateModified", + "id", + "input", + "output" + ], + "title": "Paragraph" + }, + "Input": { + "type": "object", + "additionalProperties": false, + "properties": { + "inputText": { + "type": "string" + }, + "inputType": { + "type": "string" + } + }, + "required": [ + "inputText", + "inputType" + ], + "title": "Input" + }, + "Output": { + "type": "object", + "additionalProperties": false, + "properties": { + "result": { + "type": "string" + }, + "outputType": { + "type": "string" + }, + "execution_time": { + "type": "string" + } + }, + "required": [ + "execution_time", + "outputType", + "result" + ], + "title": "Output" + } + } +} diff --git a/src/main/resources/schema/system/operational-panel.schema b/src/main/resources/schema/system/operational-panel.schema new file mode 100644 index 000000000..3cfc1540d --- /dev/null +++ b/src/main/resources/schema/system/operational-panel.schema @@ -0,0 +1,118 @@ +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "$ref": "#/definitions/panel", + "definitions": { + "panel": { + "type": "object", + "additionalProperties": false, + "properties": { + "operationalPanel": { + "$ref": "#/definitions/OperationalPanel" + } + }, + "required": [ + "operationalPanel" + ], + "title": "panel" + }, + "OperationalPanel": { + "type": "object", + "additionalProperties": false, + "properties": { + "name": { + "type": "string" + }, + "visualizations": { + "type": "array", + "items": { + "$ref": "#/definitions/Visualization" + } + }, + "timeRange": { + "$ref": "#/definitions/TimeRange" + }, + "queryFilter": { + "$ref": "#/definitions/QueryFilter" + }, + "applicationId": { + "type": "string" + } + }, + "required": [ + "applicationId", + "name", + "queryFilter", + "timeRange", + "visualizations" + ], + "title": "OperationalPanel" + }, + "QueryFilter": { + "type": "object", + "additionalProperties": false, + "properties": { + "query": { + "type": "string" + }, + "language": { + "type": "string" + } + }, + "required": [ + "language", + "query" + ], + "title": "QueryFilter" + }, + "TimeRange": { + "type": "object", + "additionalProperties": false, + "properties": { + "to": { + "type": "string" + }, + "from": { + "type": "string" + } + }, + "required": [ + "from", + "to" + ], + "title": "TimeRange" + }, + "Visualization": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "string" + }, + "savedVisualizationId": { + "type": "string" + }, + "x": { + "type": "integer" + }, + "y": { + "type": "integer" + }, + "w": { + "type": "integer" + }, + "h": { + "type": "integer" + } + }, + "required": [ + "id", + "savedVisualizationId", + "h", + "w", + "x", + "y" + ], + "title": "Visualization" + } + } +} diff --git a/src/main/resources/schema/system/samples/application.json b/src/main/resources/schema/system/samples/application.json new file mode 100644 index 000000000..020aadc4d --- /dev/null +++ b/src/main/resources/schema/system/samples/application.json @@ -0,0 +1,17 @@ +{ + "name": "Cool Application", + "description": "Application that includes multiple cool services", + "baseQuery": "source = opensearch_sample_database_flights", + "servicesEntities": [ + "Payment", + "Users", + "Purchase" + ], + "traceGroups": [ + "Payment.auto", + "Users.admin", + "Purchase.source" + ], + "panelId": "rgfQfn4BCe7Q1SIYgrrj", + "availabilityVisId": "co-Ha38BD0LU9um06tQP" +} \ No newline at end of file diff --git a/src/main/resources/schema/system/samples/catalog.json b/src/main/resources/schema/system/samples/catalog.json new file mode 100644 index 000000000..ae740e860 --- /dev/null +++ b/src/main/resources/schema/system/samples/catalog.json @@ -0,0 +1,60 @@ +{ + "catalog": "observability", + "version": "1.0", + "url": "https://github.com/opensearch-project/observability/tree/2.x/schema/observability", + "categories": [ + { + "category": "logs", + "version": "1.0", + "url": "https://github.com/opensearch-project/observability/tree/2.x/schema/observability/logs", + "components": [ + { + "component": "log", + "version": "1.0", + "url": "https://github.com/opensearch-project/observability/tree/2.x/schema/observability/logs/logs", + "container": true, + "tags": [] + }, + { + "component": "http", + "version": "1.0", + "url": "https://github.com/opensearch-project/observability/tree/2.x/schema/observability/logs/http", + "tags": [], + "container": false + }, + { + "component": "communication", + "version": "1.0", + "url": "https://github.com/opensearch-project/observability/tree/2.x/schema/observability/logs/communication", + "tags": ["web"], + "container": false + }] + }, + { + "category": "traces", + "version": "1.0", + "url": "https://github.com/opensearch-project/observability/tree/2.x/schema/observability/traces", + "components": [ + { + "component": "span", + "version": "1.0", + "url": "https://github.com/opensearch-project/observability/tree/2.x/schema/observability/traces/traces", + "tags": [], + "container": true + }] + }, + { + "category": "metrics", + "version": "1.0", + "url": "https://github.com/opensearch-project/observability/tree/2.x/schema/observability/metrics", + "components": [ + { + "component": "metric", + "version": "1.0", + "url": "https://github.com/opensearch-project/observability/tree/2.x/schema/observability/metrics/metrics", + "tags": [], + "container": true + }] + } + ] +} \ No newline at end of file diff --git a/src/main/resources/schema/system/samples/datasource.json b/src/main/resources/schema/system/samples/datasource.json new file mode 100644 index 000000000..d84d3c728 --- /dev/null +++ b/src/main/resources/schema/system/samples/datasource.json @@ -0,0 +1,12 @@ +{ + "title": "datasource-a", + "description": "my datasource-a", + "endpoint": "http://localhost:80", + "auth": { + "type": "username_password", + "credentials": { + "username": "foo", + "password": "***" + } + } +} diff --git a/src/main/resources/schema/system/samples/index-pattern.json b/src/main/resources/schema/system/samples/index-pattern.json new file mode 100644 index 000000000..40e55d55a --- /dev/null +++ b/src/main/resources/schema/system/samples/index-pattern.json @@ -0,0 +1,5 @@ +{ + "title": "*-data", + "timeFieldName": "year", + "fields": "[{\"count\":0,\"name\":\"_id\",\"type\":\"string\",\"esTypes\":[\"_id\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"count\":0,\"name\":\"_index\",\"type\":\"string\",\"esTypes\":[\"_index\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"count\":0,\"name\":\"_score\",\"type\":\"number\",\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"_source\",\"type\":\"_source\",\"esTypes\":[\"_source\"],\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"_type\",\"type\":\"string\",\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"destination.domain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"destination.resource\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"hashId\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"kind\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"serviceName\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"target.domain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"target.resource\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"traceGroupName\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true}]" +} \ No newline at end of file diff --git a/src/main/resources/schema/system/samples/integration-instance.json b/src/main/resources/schema/system/samples/integration-instance.json new file mode 100644 index 000000000..d120965bb --- /dev/null +++ b/src/main/resources/schema/system/samples/integration-instance.json @@ -0,0 +1,19 @@ +{ + "template-name": "nginx", + "dataset": "prod", + "namespace": "us_east", + "id": "nginx-prod-us_east", + "version": "0.1.0", + "description": "Nginx HTTP server collector for east cost prod systems", + "template": "https://github.com/opensearch-project/observability/blob/2.x/integrations/nginx/config.json", + "creationDate": "2016-08-29T09:12:33.001Z", + "status": "LOADED", + "assets": [ + { + "name": "sso-logs-dashboard-new.ndjson", + "creationDate": "'2016-08-29T09:12:33.001Z'", + "status": "LOADED" + } + ] +} + diff --git a/src/main/resources/schema/system/samples/integration.json b/src/main/resources/schema/system/samples/integration.json new file mode 100644 index 000000000..bfae1f5e8 --- /dev/null +++ b/src/main/resources/schema/system/samples/integration.json @@ -0,0 +1,46 @@ +{ + "template-name": "nginx", + "version": { + "integration": "0.1.0", + "schema": "1.0.0", + "resource": "^1.23.0" + }, + "description": "Nginx HTTP server collector", + "identification": "instrumentationScope.attributes.identification", + "catalog": "observability", + "components": [ + "web","http" + ], + "collection":[ + { + "logs": [{ + "info": "access logs", + "input_type":"logfile", + "dataset":"nginx.access", + "labels" :["nginx","access"], + "fields-mapping" : [ + {"alias":"http.url","field":"request_url"} , + {"alias":"http.request.body.content","field":"request_body"} + ] + }, + { + "info": "error logs", + "input_type":"logfile", + "labels" :["nginx","error"], + "dataset":"nginx.error" + }] + }, + { + "metrics": [{ + "info": "status metrics", + "input_type":"metrics", + "dataset":"nginx.status", + "labels" :["nginx","status"] + }] + } + ], + "repository": { + "url": "https://github.com/opensearch-project/observability/tree/main/integrarions/nginx" + } +} + diff --git a/src/main/resources/schema/system/samples/integrations-template-list.json b/src/main/resources/schema/system/samples/integrations-template-list.json new file mode 100644 index 000000000..10e01567d --- /dev/null +++ b/src/main/resources/schema/system/samples/integrations-template-list.json @@ -0,0 +1,23 @@ +[ + { + "template-name": "nginx", + "version": "1.0.0", + "description": "Nginx HTTP server collector", + "catalog": "observability", + "collections": ["logs","metrics"] + }, + { + "name": "apache HTTP server", + "version": "1.0.0", + "description": "Http Apache server", + "catalog": "observability", + "collections": ["logs","metrics"] + }, + { + "name": "VPC Flow Logs", + "version": "1.0.0", + "description": " Log and View Network Traffic Flows", + "catalog": "observability", + "collections": ["logs"] + } +] \ No newline at end of file diff --git a/src/main/resources/schema/system/samples/notebook.json b/src/main/resources/schema/system/samples/notebook.json new file mode 100644 index 000000000..fd7dc5341 --- /dev/null +++ b/src/main/resources/schema/system/samples/notebook.json @@ -0,0 +1,24 @@ +{ + "dateCreated" : "2020-12-11T20:51:15.509Z", + "name" : "test", + "dateModified" : "2020-12-11T21:04:55.336Z", + "backend" : "Default", + "paragraphs" : [ + { + "output" : [ + { + "result" : "# This is a markdown paragraph", + "outputType" : "MARKDOWN", + "execution_time" : "0s" + } + ], + "input" : { + "inputText" : "# This is a markdown paragraph", + "inputType" : "MARKDOWN" + }, + "dateCreated" : "2020-12-11T21:04:39.997Z", + "dateModified" : "2020-12-11T21:04:48.207Z", + "id" : "paragraph_61e96a10-af19-4c7d-ae4e-d2e449c65dff" + } + ] + } \ No newline at end of file diff --git a/src/main/resources/schema/system/samples/operationalPanel.json b/src/main/resources/schema/system/samples/operationalPanel.json new file mode 100644 index 000000000..f39ac723c --- /dev/null +++ b/src/main/resources/schema/system/samples/operationalPanel.json @@ -0,0 +1,32 @@ +{ + "operationalPanel": { + "name": "Demo Panel 1", + "visualizations": [ + { + "id": "panelViz_7ba28e34-6fd8-489d-9b9f-1f83e006fb17", + "savedVisualizationId": "oyuecXwBYVazWqOOde0o", + "x": 0, + "y": 0, + "w": 10, + "h": 10 + }, + { + "id": "panelViz_7ba28e34-6fd8-489d-9b9f-165fdv6wd611", + "savedVisualizationId": "oiuccXwBYVazWqOO1e06", + "x": 20, + "y": 20, + "w": 30, + "h": 20 + } + ], + "timeRange": { + "to": "now", + "from": "now-1d" + }, + "queryFilter": { + "query": "| where Carrier='OpenSearch-Air'", + "language": "ppl" + }, + "applicationId": "KE1Ie34BbsTr-CsB4G6Y" + } +} \ No newline at end of file diff --git a/src/main/resources/schema/system/samples/savedQuery.json b/src/main/resources/schema/system/samples/savedQuery.json new file mode 100644 index 000000000..7b7b02e1d --- /dev/null +++ b/src/main/resources/schema/system/samples/savedQuery.json @@ -0,0 +1,21 @@ +{ + "query": "source=index | where utc_time > timestamp('2021-07-01 00:00:00') and utc_time < timestamp('2021-07-02 00:00:00')", + "selected_date_range": { + "start": "now/15m", + "end": "now", + "text": "utc_time > timestamp('2021-07-01 00:00:00') and utc_time < timestamp('2021-07-02 00:00:00')" + }, + "selected_timestamp": { + "name": "utc_time", + "type": "timestamp" + }, + "selected_fields": { + "text": "| fields clientip, bytes, memory, host", + "tokens": [ + {"name":"bytes","type":"long"}, + {"name":"clientip","type":"ip"} + ] + }, + "name": "Logs between dates", + "description": "some descriptions related to this query" +} \ No newline at end of file diff --git a/src/main/resources/schema/system/samples/visualization.json b/src/main/resources/schema/system/samples/visualization.json new file mode 100644 index 000000000..e1f2e2b31 --- /dev/null +++ b/src/main/resources/schema/system/samples/visualization.json @@ -0,0 +1,30 @@ +{ + "query": "source=index | where utc_time > timestamp('2021-07-01 00:00:00') and utc_time < timestamp('2021-07-02 00:00:00')", + "selected_date_range": { + "start": "now/15m", + "end": "now", + "text": "utc_time > timestamp('2021-07-01 00:00:00') and utc_time < timestamp('2021-07-02 00:00:00')" + }, + "selected_timestamp": { + "name": "utc_time", + "type": "timestamp" + }, + "selected_fields": { + "text": "| fields clientip, bytes, memory, host", + "tokens": [ + {"name":"bytes","type":"long"}, + {"name":"clientip","type":"ip"} + ] + }, + "type": "bar", + "name": "Logs between dates", + "description": "some descriptions related to this query", + "application_id": "KE1Ie34BbsTr-CsB4G6Y", + "user_configs": "{\"dataConfig\":\"{}\",\"layoutConfig\": \"{}\"}", + "sub_type": "metric", + "units_of_measure": "hours (h)", + "labels": [ + {"label":"avg"}, + {"label":"count"} + ] +} \ No newline at end of file diff --git a/src/main/resources/schema/system/saved-query.schema b/src/main/resources/schema/system/saved-query.schema new file mode 100644 index 000000000..77f70e6f0 --- /dev/null +++ b/src/main/resources/schema/system/saved-query.schema @@ -0,0 +1,97 @@ +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "$ref": "#/definitions/SavedQuery", + "definitions": { + "SavedQuery": { + "type": "object", + "additionalProperties": false, + "properties": { + "query": { + "type": "string" + }, + "selected_date_range": { + "$ref": "#/definitions/SelectedDateRange" + }, + "selected_timestamp": { + "$ref": "#/definitions/SelectedTimestamp" + }, + "selected_fields": { + "$ref": "#/definitions/SelectedFields" + }, + "name": { + "type": "string" + }, + "description": { + "type": "string" + } + }, + "required": [ + "description", + "name", + "query", + "selected_date_range", + "selected_fields", + "selected_timestamp" + ], + "title": "SavedQuery" + }, + "SelectedDateRange": { + "type": "object", + "additionalProperties": false, + "properties": { + "start": { + "type": "string" + }, + "end": { + "type": "string" + }, + "text": { + "type": "string" + } + }, + "required": [ + "end", + "start", + "text" + ], + "title": "SelectedDateRange" + }, + "SelectedFields": { + "type": "object", + "additionalProperties": false, + "properties": { + "text": { + "type": "string" + }, + "tokens": { + "type": "array", + "items": { + "$ref": "#/definitions/SelectedTimestamp" + } + } + }, + "required": [ + "text", + "tokens" + ], + "title": "SelectedFields" + }, + "SelectedTimestamp": { + "type": "object", + "additionalProperties": false, + "properties": { + "name": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "required": [ + "name", + "type" + ], + "title": "SelectedTimestamp" + } + } +} diff --git a/src/main/resources/schema/system/visualization.schema b/src/main/resources/schema/system/visualization.schema new file mode 100644 index 000000000..0fd172f14 --- /dev/null +++ b/src/main/resources/schema/system/visualization.schema @@ -0,0 +1,137 @@ +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "$ref": "#/definitions/Visualization", + "definitions": { + "Visualization": { + "type": "object", + "additionalProperties": false, + "properties": { + "query": { + "type": "string" + }, + "selected_date_range": { + "$ref": "#/definitions/SelectedDateRange" + }, + "selected_timestamp": { + "$ref": "#/definitions/SelectedTimestamp" + }, + "selected_fields": { + "$ref": "#/definitions/SelectedFields" + }, + "type": { + "type": "string" + }, + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "application_id": { + "type": "string" + }, + "user_configs": { + "type": "string" + }, + "sub_type": { + "type": "string" + }, + "units_of_measure": { + "type": "string" + }, + "labels": { + "type": "array", + "items": { + "$ref": "#/definitions/Label" + } + } + }, + "required": [ + "application_id", + "description", + "labels", + "name", + "query", + "selected_date_range", + "selected_fields", + "selected_timestamp", + "sub_type", + "type", + "units_of_measure", + "user_configs" + ], + "title": "Visualization" + }, + "Label": { + "type": "object", + "additionalProperties": false, + "properties": { + "label": { + "type": "string" + } + }, + "required": [ + "label" + ], + "title": "Label" + }, + "SelectedDateRange": { + "type": "object", + "additionalProperties": false, + "properties": { + "start": { + "type": "string" + }, + "end": { + "type": "string" + }, + "text": { + "type": "string" + } + }, + "required": [ + "end", + "start", + "text" + ], + "title": "SelectedDateRange" + }, + "SelectedFields": { + "type": "object", + "additionalProperties": false, + "properties": { + "text": { + "type": "string" + }, + "tokens": { + "type": "array", + "items": { + "$ref": "#/definitions/SelectedTimestamp" + } + } + }, + "required": [ + "text", + "tokens" + ], + "title": "SelectedFields" + }, + "SelectedTimestamp": { + "type": "object", + "additionalProperties": false, + "properties": { + "name": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "required": [ + "name", + "type" + ], + "title": "SelectedTimestamp" + } + } +} From 43e374b7dbad7c9c3512c9b80632cf0f8965c26f Mon Sep 17 00:00:00 2001 From: Simeon Widdis Date: Tue, 28 Mar 2023 12:02:02 -0700 Subject: [PATCH 02/40] Move schema documentation to docs Signed-off-by: Simeon Widdis --- .../main/resources/schema/observability => docs/schema}/README.md | 0 .../resources/schema/observability => docs/schema}/logs/README.md | 0 .../schema}/logs/sample/http_client-log.json | 0 .../schema}/logs/sample/http_server-log.json | 0 .../schema}/logs/sample/nginx_access-log.json | 0 .../schema/observability => docs/schema}/metrics/README.md | 0 .../observability => docs/schema}/metrics/samples/gauge.json | 0 .../observability => docs/schema}/metrics/samples/histogram.json | 0 .../observability => docs/schema}/metrics/samples/load_samples.md | 0 .../schema/observability => docs/schema}/metrics/samples/sum.json | 0 .../schema/observability => docs/schema}/traces/README.md | 0 .../observability => docs/schema}/traces/samples/load_samples.md | 0 .../observability => docs/schema}/traces/samples/traceA.json | 0 .../observability => docs/schema}/traces/samples/traceB.json | 0 .../observability => docs/schema}/traces/samples/traceC.json | 0 15 files changed, 0 insertions(+), 0 deletions(-) rename {src/main/resources/schema/observability => docs/schema}/README.md (100%) rename {src/main/resources/schema/observability => docs/schema}/logs/README.md (100%) rename {src/main/resources/schema/observability => docs/schema}/logs/sample/http_client-log.json (100%) rename {src/main/resources/schema/observability => docs/schema}/logs/sample/http_server-log.json (100%) rename {src/main/resources/schema/observability => docs/schema}/logs/sample/nginx_access-log.json (100%) rename {src/main/resources/schema/observability => docs/schema}/metrics/README.md (100%) rename {src/main/resources/schema/observability => docs/schema}/metrics/samples/gauge.json (100%) rename {src/main/resources/schema/observability => docs/schema}/metrics/samples/histogram.json (100%) rename {src/main/resources/schema/observability => docs/schema}/metrics/samples/load_samples.md (100%) rename {src/main/resources/schema/observability => docs/schema}/metrics/samples/sum.json (100%) rename {src/main/resources/schema/observability => docs/schema}/traces/README.md (100%) rename {src/main/resources/schema/observability => docs/schema}/traces/samples/load_samples.md (100%) rename {src/main/resources/schema/observability => docs/schema}/traces/samples/traceA.json (100%) rename {src/main/resources/schema/observability => docs/schema}/traces/samples/traceB.json (100%) rename {src/main/resources/schema/observability => docs/schema}/traces/samples/traceC.json (100%) diff --git a/src/main/resources/schema/observability/README.md b/docs/schema/README.md similarity index 100% rename from src/main/resources/schema/observability/README.md rename to docs/schema/README.md diff --git a/src/main/resources/schema/observability/logs/README.md b/docs/schema/logs/README.md similarity index 100% rename from src/main/resources/schema/observability/logs/README.md rename to docs/schema/logs/README.md diff --git a/src/main/resources/schema/observability/logs/sample/http_client-log.json b/docs/schema/logs/sample/http_client-log.json similarity index 100% rename from src/main/resources/schema/observability/logs/sample/http_client-log.json rename to docs/schema/logs/sample/http_client-log.json diff --git a/src/main/resources/schema/observability/logs/sample/http_server-log.json b/docs/schema/logs/sample/http_server-log.json similarity index 100% rename from src/main/resources/schema/observability/logs/sample/http_server-log.json rename to docs/schema/logs/sample/http_server-log.json diff --git a/src/main/resources/schema/observability/logs/sample/nginx_access-log.json b/docs/schema/logs/sample/nginx_access-log.json similarity index 100% rename from src/main/resources/schema/observability/logs/sample/nginx_access-log.json rename to docs/schema/logs/sample/nginx_access-log.json diff --git a/src/main/resources/schema/observability/metrics/README.md b/docs/schema/metrics/README.md similarity index 100% rename from src/main/resources/schema/observability/metrics/README.md rename to docs/schema/metrics/README.md diff --git a/src/main/resources/schema/observability/metrics/samples/gauge.json b/docs/schema/metrics/samples/gauge.json similarity index 100% rename from src/main/resources/schema/observability/metrics/samples/gauge.json rename to docs/schema/metrics/samples/gauge.json diff --git a/src/main/resources/schema/observability/metrics/samples/histogram.json b/docs/schema/metrics/samples/histogram.json similarity index 100% rename from src/main/resources/schema/observability/metrics/samples/histogram.json rename to docs/schema/metrics/samples/histogram.json diff --git a/src/main/resources/schema/observability/metrics/samples/load_samples.md b/docs/schema/metrics/samples/load_samples.md similarity index 100% rename from src/main/resources/schema/observability/metrics/samples/load_samples.md rename to docs/schema/metrics/samples/load_samples.md diff --git a/src/main/resources/schema/observability/metrics/samples/sum.json b/docs/schema/metrics/samples/sum.json similarity index 100% rename from src/main/resources/schema/observability/metrics/samples/sum.json rename to docs/schema/metrics/samples/sum.json diff --git a/src/main/resources/schema/observability/traces/README.md b/docs/schema/traces/README.md similarity index 100% rename from src/main/resources/schema/observability/traces/README.md rename to docs/schema/traces/README.md diff --git a/src/main/resources/schema/observability/traces/samples/load_samples.md b/docs/schema/traces/samples/load_samples.md similarity index 100% rename from src/main/resources/schema/observability/traces/samples/load_samples.md rename to docs/schema/traces/samples/load_samples.md diff --git a/src/main/resources/schema/observability/traces/samples/traceA.json b/docs/schema/traces/samples/traceA.json similarity index 100% rename from src/main/resources/schema/observability/traces/samples/traceA.json rename to docs/schema/traces/samples/traceA.json diff --git a/src/main/resources/schema/observability/traces/samples/traceB.json b/docs/schema/traces/samples/traceB.json similarity index 100% rename from src/main/resources/schema/observability/traces/samples/traceB.json rename to docs/schema/traces/samples/traceB.json diff --git a/src/main/resources/schema/observability/traces/samples/traceC.json b/docs/schema/traces/samples/traceC.json similarity index 100% rename from src/main/resources/schema/observability/traces/samples/traceC.json rename to docs/schema/traces/samples/traceC.json From 18d71a797f8ee180cacb506667db253687d77100 Mon Sep 17 00:00:00 2001 From: Simeon Widdis Date: Tue, 28 Mar 2023 12:06:03 -0700 Subject: [PATCH 03/40] Move rest of schema documentation to docs Signed-off-by: Simeon Widdis --- docs/schema/README.md | 139 ++++++++---------- docs/schema/observability/README.md | 104 +++++++++++++ .../schema/{ => observability}/logs/README.md | 0 .../schema/observability/logs/Usage.md | 0 .../logs/sample/http_client-log.json | 0 .../logs/sample/http_server-log.json | 0 .../logs/sample/nginx_access-log.json | 0 .../{ => observability}/metrics/README.md | 0 .../metrics/samples/gauge.json | 0 .../metrics/samples/histogram.json | 0 .../metrics/samples/load_samples.md | 0 .../metrics/samples/sum.json | 0 .../{ => observability}/traces/README.md | 0 .../traces/samples/load_samples.md | 0 .../traces/samples/traceA.json | 0 .../traces/samples/traceB.json | 0 .../traces/samples/traceC.json | 0 .../schema/security/README.md | 0 .../schema/system/README.md | 0 .../schema/system/samples/application.json | 0 .../schema/system/samples/catalog.json | 0 .../schema/system/samples/datasource.json | 0 .../schema/system/samples/index-pattern.json | 0 .../system/samples/integration-instance.json | 0 .../schema/system/samples/integration.json | 0 .../samples/integrations-template-list.json | 0 .../schema/system/samples/notebook.json | 0 .../system/samples/operationalPanel.json | 0 .../schema/system/samples/savedQuery.json | 0 .../schema/system/samples/visualization.json | 0 src/main/resources/schema/README.md | 81 ---------- 31 files changed, 162 insertions(+), 162 deletions(-) create mode 100644 docs/schema/observability/README.md rename docs/schema/{ => observability}/logs/README.md (100%) rename {src/main/resources => docs}/schema/observability/logs/Usage.md (100%) rename docs/schema/{ => observability}/logs/sample/http_client-log.json (100%) rename docs/schema/{ => observability}/logs/sample/http_server-log.json (100%) rename docs/schema/{ => observability}/logs/sample/nginx_access-log.json (100%) rename docs/schema/{ => observability}/metrics/README.md (100%) rename docs/schema/{ => observability}/metrics/samples/gauge.json (100%) rename docs/schema/{ => observability}/metrics/samples/histogram.json (100%) rename docs/schema/{ => observability}/metrics/samples/load_samples.md (100%) rename docs/schema/{ => observability}/metrics/samples/sum.json (100%) rename docs/schema/{ => observability}/traces/README.md (100%) rename docs/schema/{ => observability}/traces/samples/load_samples.md (100%) rename docs/schema/{ => observability}/traces/samples/traceA.json (100%) rename docs/schema/{ => observability}/traces/samples/traceB.json (100%) rename docs/schema/{ => observability}/traces/samples/traceC.json (100%) rename {src/main/resources => docs}/schema/security/README.md (100%) rename {src/main/resources => docs}/schema/system/README.md (100%) rename {src/main/resources => docs}/schema/system/samples/application.json (100%) rename {src/main/resources => docs}/schema/system/samples/catalog.json (100%) rename {src/main/resources => docs}/schema/system/samples/datasource.json (100%) rename {src/main/resources => docs}/schema/system/samples/index-pattern.json (100%) rename {src/main/resources => docs}/schema/system/samples/integration-instance.json (100%) rename {src/main/resources => docs}/schema/system/samples/integration.json (100%) rename {src/main/resources => docs}/schema/system/samples/integrations-template-list.json (100%) rename {src/main/resources => docs}/schema/system/samples/notebook.json (100%) rename {src/main/resources => docs}/schema/system/samples/operationalPanel.json (100%) rename {src/main/resources => docs}/schema/system/samples/savedQuery.json (100%) rename {src/main/resources => docs}/schema/system/samples/visualization.json (100%) delete mode 100644 src/main/resources/schema/README.md diff --git a/docs/schema/README.md b/docs/schema/README.md index 5f101d853..c8202c693 100644 --- a/docs/schema/README.md +++ b/docs/schema/README.md @@ -1,104 +1,81 @@ -# Simple Schema for Observability +# Simple Schema for Open Search ## Background -Observability is the ability to measure a system’s current state based on the data it generates, such as logs, metrics, and traces. Observability relies on telemetry derived from instrumentation that comes from the endpoints and services. +Simple Schema for OpenSearch brings the concept of organized and structured catalog data. +A catalog of schemas is a comprehensive collection of all the possible data schemas or structures that can be used to represent information. -Observability telemetry signals (logs, metrics, traces) arriving from the system would contain all the necessary information needed to observe and monitor. +It provides a standardized way of organizing and describing the structure of data, making it easier to analyze, compare, and share data across different systems and applications. +Structured data refers to any data that is organized in a specific format or schema - for example Observability data or security data... -Modern application can have a complicated distributed architecture that combines cloud native and microservices layers. Each layer produces telemetry signals that may have different structure and information. +By using a catalog of schemas, data analysts and scientists can easily identify and understand the different structures of data, allowing them to correlate and analyze information more effectively. +One of the key benefits of a catalog of schemas is that it promotes interoperability between different systems and applications. +By using standardized schema descriptions, data can be shared and exchanged more easily, regardless of the system or application being used. -Using Simple Schema's Observability telemetry schema we can organize, correlate and investigate system behavior in a standard and well-defined manner. +The use of a catalog of schemas can also improve data quality by ensuring that data is consistent and accurate. This is because the schema provides a clear definition of the data structure and the rules for how data should be entered, validated, and stored. -Observability telemetry schema defines the following components - **logs, traces and metrics**. +## OpenSearch Schemas -**Logs** provide comprehensive system details, such as a fault and the specific time when the fault occurred. By analyzing the logs, one can troubleshoot code and identify where and why the error occurred. +Opensearch supports out of the box the following schemas + - [Observability](observability/README.md) + - [Security](security/README.md) + - [System](system/README.md) -**Traces** represent the entire journey of a request or action as it moves through all the layers of a distributed system. Traces allow you to profile and observe systems, especially containerized applications, serverless architectures, or microservices architecture. +### Observability +Simple Schema for [Observability](https://github.com/opensearch-project/observability) allows ingestion of both (OTEL/ECS) formats and internally consolidate them to best of its capabilities for presenting a unified Observability platform. -**Metrics** provide a numerical representation of data that can be used to determine a service or component’s overall behaviour over time. +### Security +OpenSearch Security is a [plugin](https://github.com/opensearch-project/security) for OpenSearch that offers encryption, authentication and authorization. When combined with OpenSearch Security-Advanced Modules, it supports authentication via Active Directory, LDAP, Kerberos, JSON web tokens, SAML, OpenID and more. It includes fine grained role-based access control to indices, documents and fields. It also provides multi-tenancy support in OpenSearch Dashboards. +### System +System represents the internal structure of Opensearch's `.dashboard` entities such as `dashboard`, `notebook`, `save-query` `integration`. Every saved object may declare itself in the system +catalog folder and publish a corresponding schema. This capability will allow validation of these objects and also simplify structure evolution using this schema. -In many occasions, correlation between the logs, traces and metrics is mandatory to be able to monitor and understand how the system is behaving. In addition, the distributed nature of the application produces multiple formats of telemetry signals arriving from different components ( network router, web server, database) +### Catalog Loading +During Integration plugin loading, it will go over all the Opensearch's schema supported catalogs and generate the appropriate templates representing them. +This will allow any future Integration using these catalogs without the need to explicitly defining them thus maintaining a unified common schema. -For such correlation to be possible the industry has formulated several protocols ([OTEL](https://github.com/open-telemetry), [ECS](https://github.com/elastic/ecs), [OpenMetrics](https://github.com/OpenObservability/OpenMetrics)) for communicating these signals - the Observability schemas. +Each catalog may support semantic versioning so that it may evolve its schema as needed. +In the future, the catalog will enable to associate domains with catalogs and allow externally importing catalogs into Opensearch for additional collaboration. ---- -## Schema Aware Components +### Catalog Structure +A catalog is structured in the following way: -The role of the Observability [plugin](https://github.com/opensearch-project/observability) is intended to allow maximum flexibility and not imposing a strict Index structure of the data source. Nevertheless, the modern nature of distributed application and the vast amount of telemetry producers is changing this perception. + - Catalog named folder: `Observability` + - Categories named folder : `Logs`, `Traces`, `Metrics` + - Component named file : `http` , `communication` , `traces` , `metrics` -Today many of the Observability solutions (splunk, datadog, dynatrace) recommend using a consolidated schema to represent the entire variance of log/trace/metrics producers. +Each level encapsulates additional internal structure that allows a greater level of composability and agility. +The details of each catalog structure is described in the [catalog.json](system/samples/catalog.json) file that resides in the root level of each catalog folder. -This allows monitoring, incidents investigation and corrections process to become simpler, maintainable and reproducible. +**Component** +The component is the leaf level definition of the catalog hierarchy, it details the actual building blocks of the catalog's types and fields. +Each component has two flavours: -A Schema-Aware visualization component is a component which assumes the existence of specific index/indices name patterns and expects these indices to have a specific structure - a schema. + - `$component.mapping` - describes how the type is physically stored in the underlying index + - `$component.mapping` - describing the actual json schema for this component type -As an example we can see that **Trace-Analytics** is a schema-aware visual component since it directly assumes the traces & serviceMap indices exist and expects them to follow a specific structure. +A component may be classified as a `container` which has the ability to group / combine multiple components inside. -This definition doesn’t change the existing status of visualization components which are not “Schema Aware” but it only regulates which Visual components would benefit using a schema and which will be agnostic of its content. - -Operation Panel for example, are not “Schema Aware” since they don’t assume in advanced the existence of a specific index nor do they expect the index they display to have a specific structure. - -## Data Model - -Simple Schema for Observability allows ingestion of both (OTEL/ECS) formats and internally consolidate them to best of its capabilities for presenting a unified Observability platform. - -## Observability index naming - -The Observability indices would follow the recommended for immutable data stream ingestion pattern using the [data_stream concepts](https://opensearch.org/docs/latest/opensearch/data-streams/) - -Index pattern will follow the next naming template `sso_{type}`-`{dataset}`-`{namespace}` - - - **type** - indicated the observability high level types "logs", "metrics", "traces" (prefixed by the `sso_` schema convention ) - - **dataset** - The field can contain anything that classify the source of the data - such as `nginx.access` - - **namespace** - A user defined namespace - mainly useful to allow grouping of data such as production grade, geography classification - -This strategy allows two degrees of naming freedom: dataset and namespace. For example a customer may want to route the nginx logs from two geographical areas into two different indices: - - - `sso_logs-nginx-us` - - `sso_logs-nginx-eu` - -This type of distinction also allows for creation of crosscutting queries by setting the next index query pattern `sso_logs-nginx-*` or by using a geographic based crosscutting query `sso_logs-*-eu`. - -## Data index routing - -The [ingestion component](https://github.com/opensearch-project/data-prepper) which is responsible for ingesting the Observability signals is responsible to route the data into the relevant indices. - -The `sso_{type}-{dataset}-{namespace}` combination dictates the target index, `{type}` is prefixed with the `sso_` prefix into one of the supported type: - - - Traces - `sso_traces` - - Metrics - `sso_metrics` - - Logs - `sso_logs` - -For example if within the ingested log contains the following section: -```json -{ +For example, we can examine the [`logs`](observability/logs/logs.mapping) component that has the capacity to combine additional components (such as `http`, `communication` and more) +```json5 + ... + "composed_of": [ + "http_template", + "communication_template" + ], ... - "attributes": { - "data_stream": { - "type": "span", - "dataset": "mysql", - "namespace": "prod" - } - } -} ``` -This indicates that the target index for this observability signal should be `sso_traces`-`mysql`-`prod` index that follows uses the traces schema mapping. - -## Observability Index templates - -With the expectation of multiple Observability data providers and the need to consolidate all to a single common schema - the Observability plugin will take the following responsibilities : - - - Define and create all the signals **index templates** upon loading - - Publish a versioned schema file (Json Schema) for each signal type for general validation usage by any 3rd party +A component also has a list of `tags` which are aliases for the component name which can be used to reference it directly by an integration components list. -## Observability Ingestion pipeline -The responsibility on an **Observability-ingestion-pipeline** is to create the actual `data_stream` in which it is expecting to ingest into. - -This `data_stream` will use one of the Observability ready-made index templates (Metrics,Traces and Logs) and conform with the above naming pattern (`sso_{type}`-`{dataset}`-`{namespace}`) - -**If the ingesting party has a need to update the template default index setting (shards, replicas ) it may do so before the actual creation of the data_stream.** - -### Note -It is important to mention that these new capabilities would not change or prevent existing customer usage of the system and continue to allow proprietary usage. +```json5 + ... + { + "component": "communication", + "version": "1.0", + "url": "https://github.com/opensearch-project/observability/tree/2.x/schema/observability/logs/communication", + "tags": ["web"], + "container": false + } + ... +``` \ No newline at end of file diff --git a/docs/schema/observability/README.md b/docs/schema/observability/README.md new file mode 100644 index 000000000..5f101d853 --- /dev/null +++ b/docs/schema/observability/README.md @@ -0,0 +1,104 @@ +# Simple Schema for Observability + +## Background +Observability is the ability to measure a system’s current state based on the data it generates, such as logs, metrics, and traces. Observability relies on telemetry derived from instrumentation that comes from the endpoints and services. + +Observability telemetry signals (logs, metrics, traces) arriving from the system would contain all the necessary information needed to observe and monitor. + +Modern application can have a complicated distributed architecture that combines cloud native and microservices layers. Each layer produces telemetry signals that may have different structure and information. + +Using Simple Schema's Observability telemetry schema we can organize, correlate and investigate system behavior in a standard and well-defined manner. + +Observability telemetry schema defines the following components - **logs, traces and metrics**. + +**Logs** provide comprehensive system details, such as a fault and the specific time when the fault occurred. By analyzing the logs, one can troubleshoot code and identify where and why the error occurred. + +**Traces** represent the entire journey of a request or action as it moves through all the layers of a distributed system. Traces allow you to profile and observe systems, especially containerized applications, serverless architectures, or microservices architecture. + +**Metrics** provide a numerical representation of data that can be used to determine a service or component’s overall behaviour over time. + + +In many occasions, correlation between the logs, traces and metrics is mandatory to be able to monitor and understand how the system is behaving. In addition, the distributed nature of the application produces multiple formats of telemetry signals arriving from different components ( network router, web server, database) + +For such correlation to be possible the industry has formulated several protocols ([OTEL](https://github.com/open-telemetry), [ECS](https://github.com/elastic/ecs), [OpenMetrics](https://github.com/OpenObservability/OpenMetrics)) for communicating these signals - the Observability schemas. + +--- +## Schema Aware Components + +The role of the Observability [plugin](https://github.com/opensearch-project/observability) is intended to allow maximum flexibility and not imposing a strict Index structure of the data source. Nevertheless, the modern nature of distributed application and the vast amount of telemetry producers is changing this perception. + +Today many of the Observability solutions (splunk, datadog, dynatrace) recommend using a consolidated schema to represent the entire variance of log/trace/metrics producers. + +This allows monitoring, incidents investigation and corrections process to become simpler, maintainable and reproducible. + + +A Schema-Aware visualization component is a component which assumes the existence of specific index/indices name patterns and expects these indices to have a specific structure - a schema. + +As an example we can see that **Trace-Analytics** is a schema-aware visual component since it directly assumes the traces & serviceMap indices exist and expects them to follow a specific structure. + +This definition doesn’t change the existing status of visualization components which are not “Schema Aware” but it only regulates which Visual components would benefit using a schema and which will be agnostic of its content. + +Operation Panel for example, are not “Schema Aware” since they don’t assume in advanced the existence of a specific index nor do they expect the index they display to have a specific structure. + +## Data Model + +Simple Schema for Observability allows ingestion of both (OTEL/ECS) formats and internally consolidate them to best of its capabilities for presenting a unified Observability platform. + +## Observability index naming + +The Observability indices would follow the recommended for immutable data stream ingestion pattern using the [data_stream concepts](https://opensearch.org/docs/latest/opensearch/data-streams/) + +Index pattern will follow the next naming template `sso_{type}`-`{dataset}`-`{namespace}` + + - **type** - indicated the observability high level types "logs", "metrics", "traces" (prefixed by the `sso_` schema convention ) + - **dataset** - The field can contain anything that classify the source of the data - such as `nginx.access` + - **namespace** - A user defined namespace - mainly useful to allow grouping of data such as production grade, geography classification + +This strategy allows two degrees of naming freedom: dataset and namespace. For example a customer may want to route the nginx logs from two geographical areas into two different indices: + + - `sso_logs-nginx-us` + - `sso_logs-nginx-eu` + +This type of distinction also allows for creation of crosscutting queries by setting the next index query pattern `sso_logs-nginx-*` or by using a geographic based crosscutting query `sso_logs-*-eu`. + +## Data index routing + +The [ingestion component](https://github.com/opensearch-project/data-prepper) which is responsible for ingesting the Observability signals is responsible to route the data into the relevant indices. + +The `sso_{type}-{dataset}-{namespace}` combination dictates the target index, `{type}` is prefixed with the `sso_` prefix into one of the supported type: + + - Traces - `sso_traces` + - Metrics - `sso_metrics` + - Logs - `sso_logs` + +For example if within the ingested log contains the following section: +```json +{ + ... + "attributes": { + "data_stream": { + "type": "span", + "dataset": "mysql", + "namespace": "prod" + } + } +} +``` +This indicates that the target index for this observability signal should be `sso_traces`-`mysql`-`prod` index that follows uses the traces schema mapping. + +## Observability Index templates + +With the expectation of multiple Observability data providers and the need to consolidate all to a single common schema - the Observability plugin will take the following responsibilities : + + - Define and create all the signals **index templates** upon loading + - Publish a versioned schema file (Json Schema) for each signal type for general validation usage by any 3rd party + +## Observability Ingestion pipeline +The responsibility on an **Observability-ingestion-pipeline** is to create the actual `data_stream` in which it is expecting to ingest into. + +This `data_stream` will use one of the Observability ready-made index templates (Metrics,Traces and Logs) and conform with the above naming pattern (`sso_{type}`-`{dataset}`-`{namespace}`) + +**If the ingesting party has a need to update the template default index setting (shards, replicas ) it may do so before the actual creation of the data_stream.** + +### Note +It is important to mention that these new capabilities would not change or prevent existing customer usage of the system and continue to allow proprietary usage. diff --git a/docs/schema/logs/README.md b/docs/schema/observability/logs/README.md similarity index 100% rename from docs/schema/logs/README.md rename to docs/schema/observability/logs/README.md diff --git a/src/main/resources/schema/observability/logs/Usage.md b/docs/schema/observability/logs/Usage.md similarity index 100% rename from src/main/resources/schema/observability/logs/Usage.md rename to docs/schema/observability/logs/Usage.md diff --git a/docs/schema/logs/sample/http_client-log.json b/docs/schema/observability/logs/sample/http_client-log.json similarity index 100% rename from docs/schema/logs/sample/http_client-log.json rename to docs/schema/observability/logs/sample/http_client-log.json diff --git a/docs/schema/logs/sample/http_server-log.json b/docs/schema/observability/logs/sample/http_server-log.json similarity index 100% rename from docs/schema/logs/sample/http_server-log.json rename to docs/schema/observability/logs/sample/http_server-log.json diff --git a/docs/schema/logs/sample/nginx_access-log.json b/docs/schema/observability/logs/sample/nginx_access-log.json similarity index 100% rename from docs/schema/logs/sample/nginx_access-log.json rename to docs/schema/observability/logs/sample/nginx_access-log.json diff --git a/docs/schema/metrics/README.md b/docs/schema/observability/metrics/README.md similarity index 100% rename from docs/schema/metrics/README.md rename to docs/schema/observability/metrics/README.md diff --git a/docs/schema/metrics/samples/gauge.json b/docs/schema/observability/metrics/samples/gauge.json similarity index 100% rename from docs/schema/metrics/samples/gauge.json rename to docs/schema/observability/metrics/samples/gauge.json diff --git a/docs/schema/metrics/samples/histogram.json b/docs/schema/observability/metrics/samples/histogram.json similarity index 100% rename from docs/schema/metrics/samples/histogram.json rename to docs/schema/observability/metrics/samples/histogram.json diff --git a/docs/schema/metrics/samples/load_samples.md b/docs/schema/observability/metrics/samples/load_samples.md similarity index 100% rename from docs/schema/metrics/samples/load_samples.md rename to docs/schema/observability/metrics/samples/load_samples.md diff --git a/docs/schema/metrics/samples/sum.json b/docs/schema/observability/metrics/samples/sum.json similarity index 100% rename from docs/schema/metrics/samples/sum.json rename to docs/schema/observability/metrics/samples/sum.json diff --git a/docs/schema/traces/README.md b/docs/schema/observability/traces/README.md similarity index 100% rename from docs/schema/traces/README.md rename to docs/schema/observability/traces/README.md diff --git a/docs/schema/traces/samples/load_samples.md b/docs/schema/observability/traces/samples/load_samples.md similarity index 100% rename from docs/schema/traces/samples/load_samples.md rename to docs/schema/observability/traces/samples/load_samples.md diff --git a/docs/schema/traces/samples/traceA.json b/docs/schema/observability/traces/samples/traceA.json similarity index 100% rename from docs/schema/traces/samples/traceA.json rename to docs/schema/observability/traces/samples/traceA.json diff --git a/docs/schema/traces/samples/traceB.json b/docs/schema/observability/traces/samples/traceB.json similarity index 100% rename from docs/schema/traces/samples/traceB.json rename to docs/schema/observability/traces/samples/traceB.json diff --git a/docs/schema/traces/samples/traceC.json b/docs/schema/observability/traces/samples/traceC.json similarity index 100% rename from docs/schema/traces/samples/traceC.json rename to docs/schema/observability/traces/samples/traceC.json diff --git a/src/main/resources/schema/security/README.md b/docs/schema/security/README.md similarity index 100% rename from src/main/resources/schema/security/README.md rename to docs/schema/security/README.md diff --git a/src/main/resources/schema/system/README.md b/docs/schema/system/README.md similarity index 100% rename from src/main/resources/schema/system/README.md rename to docs/schema/system/README.md diff --git a/src/main/resources/schema/system/samples/application.json b/docs/schema/system/samples/application.json similarity index 100% rename from src/main/resources/schema/system/samples/application.json rename to docs/schema/system/samples/application.json diff --git a/src/main/resources/schema/system/samples/catalog.json b/docs/schema/system/samples/catalog.json similarity index 100% rename from src/main/resources/schema/system/samples/catalog.json rename to docs/schema/system/samples/catalog.json diff --git a/src/main/resources/schema/system/samples/datasource.json b/docs/schema/system/samples/datasource.json similarity index 100% rename from src/main/resources/schema/system/samples/datasource.json rename to docs/schema/system/samples/datasource.json diff --git a/src/main/resources/schema/system/samples/index-pattern.json b/docs/schema/system/samples/index-pattern.json similarity index 100% rename from src/main/resources/schema/system/samples/index-pattern.json rename to docs/schema/system/samples/index-pattern.json diff --git a/src/main/resources/schema/system/samples/integration-instance.json b/docs/schema/system/samples/integration-instance.json similarity index 100% rename from src/main/resources/schema/system/samples/integration-instance.json rename to docs/schema/system/samples/integration-instance.json diff --git a/src/main/resources/schema/system/samples/integration.json b/docs/schema/system/samples/integration.json similarity index 100% rename from src/main/resources/schema/system/samples/integration.json rename to docs/schema/system/samples/integration.json diff --git a/src/main/resources/schema/system/samples/integrations-template-list.json b/docs/schema/system/samples/integrations-template-list.json similarity index 100% rename from src/main/resources/schema/system/samples/integrations-template-list.json rename to docs/schema/system/samples/integrations-template-list.json diff --git a/src/main/resources/schema/system/samples/notebook.json b/docs/schema/system/samples/notebook.json similarity index 100% rename from src/main/resources/schema/system/samples/notebook.json rename to docs/schema/system/samples/notebook.json diff --git a/src/main/resources/schema/system/samples/operationalPanel.json b/docs/schema/system/samples/operationalPanel.json similarity index 100% rename from src/main/resources/schema/system/samples/operationalPanel.json rename to docs/schema/system/samples/operationalPanel.json diff --git a/src/main/resources/schema/system/samples/savedQuery.json b/docs/schema/system/samples/savedQuery.json similarity index 100% rename from src/main/resources/schema/system/samples/savedQuery.json rename to docs/schema/system/samples/savedQuery.json diff --git a/src/main/resources/schema/system/samples/visualization.json b/docs/schema/system/samples/visualization.json similarity index 100% rename from src/main/resources/schema/system/samples/visualization.json rename to docs/schema/system/samples/visualization.json diff --git a/src/main/resources/schema/README.md b/src/main/resources/schema/README.md deleted file mode 100644 index c8202c693..000000000 --- a/src/main/resources/schema/README.md +++ /dev/null @@ -1,81 +0,0 @@ -# Simple Schema for Open Search - -## Background -Simple Schema for OpenSearch brings the concept of organized and structured catalog data. -A catalog of schemas is a comprehensive collection of all the possible data schemas or structures that can be used to represent information. - -It provides a standardized way of organizing and describing the structure of data, making it easier to analyze, compare, and share data across different systems and applications. -Structured data refers to any data that is organized in a specific format or schema - for example Observability data or security data... - -By using a catalog of schemas, data analysts and scientists can easily identify and understand the different structures of data, allowing them to correlate and analyze information more effectively. -One of the key benefits of a catalog of schemas is that it promotes interoperability between different systems and applications. -By using standardized schema descriptions, data can be shared and exchanged more easily, regardless of the system or application being used. - -The use of a catalog of schemas can also improve data quality by ensuring that data is consistent and accurate. This is because the schema provides a clear definition of the data structure and the rules for how data should be entered, validated, and stored. - -## OpenSearch Schemas - -Opensearch supports out of the box the following schemas - - [Observability](observability/README.md) - - [Security](security/README.md) - - [System](system/README.md) - -### Observability -Simple Schema for [Observability](https://github.com/opensearch-project/observability) allows ingestion of both (OTEL/ECS) formats and internally consolidate them to best of its capabilities for presenting a unified Observability platform. - -### Security -OpenSearch Security is a [plugin](https://github.com/opensearch-project/security) for OpenSearch that offers encryption, authentication and authorization. When combined with OpenSearch Security-Advanced Modules, it supports authentication via Active Directory, LDAP, Kerberos, JSON web tokens, SAML, OpenID and more. It includes fine grained role-based access control to indices, documents and fields. It also provides multi-tenancy support in OpenSearch Dashboards. - -### System -System represents the internal structure of Opensearch's `.dashboard` entities such as `dashboard`, `notebook`, `save-query` `integration`. Every saved object may declare itself in the system -catalog folder and publish a corresponding schema. This capability will allow validation of these objects and also simplify structure evolution using this schema. - -### Catalog Loading -During Integration plugin loading, it will go over all the Opensearch's schema supported catalogs and generate the appropriate templates representing them. -This will allow any future Integration using these catalogs without the need to explicitly defining them thus maintaining a unified common schema. - -Each catalog may support semantic versioning so that it may evolve its schema as needed. -In the future, the catalog will enable to associate domains with catalogs and allow externally importing catalogs into Opensearch for additional collaboration. - -### Catalog Structure -A catalog is structured in the following way: - - - Catalog named folder: `Observability` - - Categories named folder : `Logs`, `Traces`, `Metrics` - - Component named file : `http` , `communication` , `traces` , `metrics` - -Each level encapsulates additional internal structure that allows a greater level of composability and agility. -The details of each catalog structure is described in the [catalog.json](system/samples/catalog.json) file that resides in the root level of each catalog folder. - -**Component** -The component is the leaf level definition of the catalog hierarchy, it details the actual building blocks of the catalog's types and fields. - -Each component has two flavours: - - - `$component.mapping` - describes how the type is physically stored in the underlying index - - `$component.mapping` - describing the actual json schema for this component type - -A component may be classified as a `container` which has the ability to group / combine multiple components inside. - -For example, we can examine the [`logs`](observability/logs/logs.mapping) component that has the capacity to combine additional components (such as `http`, `communication` and more) -```json5 - ... - "composed_of": [ - "http_template", - "communication_template" - ], - ... -``` -A component also has a list of `tags` which are aliases for the component name which can be used to reference it directly by an integration components list. - -```json5 - ... - { - "component": "communication", - "version": "1.0", - "url": "https://github.com/opensearch-project/observability/tree/2.x/schema/observability/logs/communication", - "tags": ["web"], - "container": false - } - ... -``` \ No newline at end of file From ea46eb9d7a51b2dec16cf1dab33c7ebb0efb4fdc Mon Sep 17 00:00:00 2001 From: Simeon Widdis Date: Thu, 30 Mar 2023 11:54:03 -0700 Subject: [PATCH 04/40] Pull CLI from 2.x Signed-off-by: Simeon Widdis --- scripts/integrations-cli/.gitignore | 180 ++++++++++++++++++ scripts/integrations-cli/helpers/__init__.py | 2 + scripts/integrations-cli/helpers/constants.py | 25 +++ scripts/integrations-cli/helpers/create.py | 52 +++++ scripts/integrations-cli/helpers/validate.py | 13 ++ scripts/integrations-cli/integrations-cli.py | 124 ++++++++++++ scripts/integrations-cli/requirements.txt | 12 ++ scripts/integrations-cli/tests/__init__.py | 1 + .../integrations-cli/tests/test_validate.py | 33 ++++ 9 files changed, 442 insertions(+) create mode 100644 scripts/integrations-cli/.gitignore create mode 100644 scripts/integrations-cli/helpers/__init__.py create mode 100644 scripts/integrations-cli/helpers/constants.py create mode 100644 scripts/integrations-cli/helpers/create.py create mode 100644 scripts/integrations-cli/helpers/validate.py create mode 100644 scripts/integrations-cli/integrations-cli.py create mode 100644 scripts/integrations-cli/requirements.txt create mode 100644 scripts/integrations-cli/tests/__init__.py create mode 100644 scripts/integrations-cli/tests/test_validate.py diff --git a/scripts/integrations-cli/.gitignore b/scripts/integrations-cli/.gitignore new file mode 100644 index 000000000..1dbd8b5a9 --- /dev/null +++ b/scripts/integrations-cli/.gitignore @@ -0,0 +1,180 @@ +# Directories used by CLI +artifacts +integrations + +# Created by https://www.toptal.com/developers/gitignore/api/python +# Edit at https://www.toptal.com/developers/gitignore?templates=python + +### Python ### +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/#use-with-ide +.pdm.toml + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/ + +### Python Patch ### +# Poetry local configuration file - https://python-poetry.org/docs/configuration/#local-configuration +poetry.toml + +# ruff +.ruff_cache/ + +# LSP config files +pyrightconfig.json + +# End of https://www.toptal.com/developers/gitignore/api/python diff --git a/scripts/integrations-cli/helpers/__init__.py b/scripts/integrations-cli/helpers/__init__.py new file mode 100644 index 000000000..05afb1b7e --- /dev/null +++ b/scripts/integrations-cli/helpers/__init__.py @@ -0,0 +1,2 @@ +from . import constants, validate +from .create import IntegrationBuilder diff --git a/scripts/integrations-cli/helpers/constants.py b/scripts/integrations-cli/helpers/constants.py new file mode 100644 index 000000000..446619a2e --- /dev/null +++ b/scripts/integrations-cli/helpers/constants.py @@ -0,0 +1,25 @@ +import glob +import json +import os + +_SCHEMA_ROOT = "../../src/main/resources/schema" + +DEFAULT_CONFIG = { + "template-name": "default", + "version": {"integration": "0.1.0", "schema": "1.0.0", "resource": "^1.23.0"}, + "description": "", + "identification": "", + "catalog": "observability", + "components": [], + "collection": [], + "repository": {"url": "https://example.com/"}, +} + +SCHEMAS = {} + +# For now, assume we're running in the current relative directory +if os.path.isdir(_SCHEMA_ROOT): + for filename in glob.glob(os.path.join(_SCHEMA_ROOT, "**/*.schema"), recursive=True): + schema_name = os.path.split(filename)[1] + with open(filename, "r") as schema_file: + SCHEMAS[schema_name] = json.load(schema_file) diff --git a/scripts/integrations-cli/helpers/create.py b/scripts/integrations-cli/helpers/create.py new file mode 100644 index 000000000..b7e25c33a --- /dev/null +++ b/scripts/integrations-cli/helpers/create.py @@ -0,0 +1,52 @@ +import json +import os +from urllib import parse +from copy import deepcopy + +from .constants import DEFAULT_CONFIG +from .validate import validate_config +import re + + +class IntegrationBuilder: + def __init__(self): + self.path = None + self.config = deepcopy(DEFAULT_CONFIG) + + def with_name(self, name: str) -> "IntegrationBuilder": + self.config["template-name"] = name + return self + + def with_path(self, path: str) -> "IntegrationBuilder": + self.path = path + self.config["repository"]["url"] = f"file://{path}" + return self + + def with_schema_version(self, version: str) -> "IntegrationBuilder": + if not re.match(r"^\d+\.\d+\.\d+", version): + raise ValueError("Invalid version") + self.config["version"]["schema"] = version + + def with_resource_version(self, version: str) -> "IntegrationBuilder": + if not re.match(r"^\^?\d+\.\d+\.\d+", version): + raise ValueError("Invalid version") + self.config["version"]["resource"] = version + + def with_description(self, desc: str) -> "IntegrationBuilder": + self.config["description"] = desc + + def with_catalog(self, catalog: str) -> "IntegrationBuilder": + self.config["catalog"] = catalog + + def with_repository(self, repo_url: str) -> "IntegrationBuilder": + if not parse.urlparse(repo_url): + raise ValueError("Invalid URL") + self.config["repository"]["url"] = repo_url + + def build(self): + assert self.path is not None + os.makedirs(self.path, exist_ok=True) + files = {"config.json": validate_config(self.config)} + for filename, data in files.items(): + with open(os.path.join(self.path, filename), "w") as file: + json.dump(data, file, ensure_ascii=False, indent=2) diff --git a/scripts/integrations-cli/helpers/validate.py b/scripts/integrations-cli/helpers/validate.py new file mode 100644 index 000000000..dd9fd3411 --- /dev/null +++ b/scripts/integrations-cli/helpers/validate.py @@ -0,0 +1,13 @@ +import logging + +import jsonschema + +from .constants import SCHEMAS + + +def validate_config(config: dict) -> dict: + if "integration.schema" in SCHEMAS: + jsonschema.validate(instance=config, schema=SCHEMAS["integration.schema"]) + else: + raise ValueError("integration.schema does not exist") + return config diff --git a/scripts/integrations-cli/integrations-cli.py b/scripts/integrations-cli/integrations-cli.py new file mode 100644 index 000000000..4cdc784e7 --- /dev/null +++ b/scripts/integrations-cli/integrations-cli.py @@ -0,0 +1,124 @@ +#!./venv/bin/python3 +import json +import os +from urllib import parse +import zipfile + +import click +import jsonschema +from termcolor import colored + +import helpers + + +@click.group() +def integrations_cli(): + """Create and maintain Integrations for the OpenSearch Integrations Plugin.""" + pass + + +def do_add_component(_builder: helpers.IntegrationBuilder): + click.echo("Interactive component definition is work-in-progress. Sorry!") + return "n" + + +@integrations_cli.command() +@click.argument("name") +def create(name: str): + """Create a new Integration from a specified template.""" + click.echo(f"Creating new integration '{name}'") + integration_path = os.path.join(os.getcwd(), "integrations", name) + if os.path.exists(integration_path) and len(os.listdir(integration_path)) != 0: + raise click.ClickException( + f"destination path '{integration_path}' exists and is non-empty" + ) + for subdir in ["assets", "info", "samples", "schema", "test"]: + os.makedirs(os.path.join(integration_path, subdir)) + builder = helpers.IntegrationBuilder().with_name(name).with_path(integration_path) + click.prompt( + "Schema version", default="1.0.0", type=builder.with_schema_version + ) + click.prompt( + "Resource version", type=builder.with_resource_version + ) + click.prompt( + "Integration description", default="", type=builder.with_description + ) + builder.with_catalog(click.prompt( + "Integration catalog", + type=click.Choice(["observability", "security"]) + )) + click.prompt( + "Integration Repository URL", + default="file://" + integration_path, + type=builder.with_repository + ) + add_component = click.prompt( + "Would you like to configure components interactively? (y/n)", + type=click.Choice(["y", "n"], False), + show_choices=False + ) + while add_component == "y": + add_component = do_add_component(builder) + builder.build() + click.echo(colored(f"Integration created at '{integration_path}'", "green")) + + +def full_integration_is_valid(name: str) -> bool: + integration_path = os.path.join(os.getcwd(), "integrations", name) + integration_parts = {"config.json": helpers.validate.validate_config} + encountered_errors = False + for item, validator in integration_parts.items(): + item_path = os.path.join(integration_path, item) + with open(item_path, "r") as item_data: + try: + loaded = json.load(item_data) + validator(loaded) + except jsonschema.exceptions.ValidationError as err: + click.echo(colored(f"'{item_path}' is invalid", "red")) + err_msg = ("> " + str(err)).replace("\n", "\n> ") + click.echo(colored(err_msg, "red"), err=True) + encountered_errors = True + return not encountered_errors + + +@integrations_cli.command() +@click.argument("name") +def check(name: str): + """Analyze the current Integration and report errors.""" + click.echo(f"Checking integration '{name}'") + if full_integration_is_valid(name): + click.echo(colored("Integration is valid", "green")) + + +@integrations_cli.command() +@click.argument("name") +def package(name: str): + """Package the current integration for use in OpenSearch.""" + click.echo(f"Checking integration '{name}'") + if not full_integration_is_valid(name): + return + click.echo(f"Packaging integration '{name}'") + os.makedirs("artifacts", exist_ok=True) + integration_path = os.path.join(os.getcwd(), "integrations", name) + artifact_path = os.path.join("artifacts", f"{name}.zip") + with zipfile.ZipFile(artifact_path, "w") as zf: + for _, dirnames, filenames in os.walk(integration_path): + for item in dirnames + filenames: + zf.write(os.path.join(integration_path, item), arcname=item) + click.echo(colored(f"Packaged integration as '{artifact_path}'", "green")) + + +@integrations_cli.command() +@click.argument("name") +@click.argument("opensearch_url", default="http://localhost:9200/") +def upload(name: str, opensearch_url: str): + url = parse.urlparse(opensearch_url) + if not url: + click.echo(colored("Invalid URL", "red")) + return + print(url) + + +if __name__ == "__main__": + integrations_cli() diff --git a/scripts/integrations-cli/requirements.txt b/scripts/integrations-cli/requirements.txt new file mode 100644 index 000000000..906ddc9bd --- /dev/null +++ b/scripts/integrations-cli/requirements.txt @@ -0,0 +1,12 @@ +attrs==22.2.0 +black==23.1.0 +click==8.1.3 +isort==5.12.0 +jsonschema==4.17.3 +mypy-extensions==1.0.0 +packaging==23.0 +pathspec==0.11.1 +platformdirs==3.1.1 +pyrsistent==0.19.3 +termcolor==2.2.0 +tomli==2.0.1 diff --git a/scripts/integrations-cli/tests/__init__.py b/scripts/integrations-cli/tests/__init__.py new file mode 100644 index 000000000..70119999d --- /dev/null +++ b/scripts/integrations-cli/tests/__init__.py @@ -0,0 +1 @@ +# Empty init file required for test discovery diff --git a/scripts/integrations-cli/tests/test_validate.py b/scripts/integrations-cli/tests/test_validate.py new file mode 100644 index 000000000..973b85cee --- /dev/null +++ b/scripts/integrations-cli/tests/test_validate.py @@ -0,0 +1,33 @@ +import unittest +from copy import deepcopy + +import jsonschema + +import helpers.constants as constants +import helpers.validate as validate + + +class TestSchemas(unittest.TestCase): + def test_config_schema_is_valid(self): + config_schema = constants.SCHEMAS["integration.schema"] + jsonschema.Draft6Validator.check_schema(config_schema) + + +class TestDefaults(unittest.TestCase): + def test_default_config_is_valid(self): + config_schema = constants.SCHEMAS["integration.schema"] + jsonschema.validate(constants.DEFAULT_CONFIG, config_schema) + + +class TestFailingValidations(unittest.TestCase): + def test_default_with_no_name_is_invalid(self): + config = deepcopy(constants.DEFAULT_CONFIG) + del config["template-name"] + with self.assertRaises(jsonschema.exceptions.ValidationError): + validate.validate_config(config) + + def test_default_with_integer_description_is_invalid(self): + config = deepcopy(constants.DEFAULT_CONFIG) + config["description"] = 0 + with self.assertRaises(jsonschema.exceptions.ValidationError): + validate.validate_config(config) From 472508d2c2a874511c27ab6c6d30701bade8a986 Mon Sep 17 00:00:00 2001 From: Simeon Widdis Date: Fri, 31 Mar 2023 13:54:11 -0700 Subject: [PATCH 05/40] Commit CLI project to Poetry Poetry is an alternative package manager for Python that is more scalable. It's used in various large Python projects to good effect. https://python-poetry.org/ Signed-off-by: Simeon Widdis --- scripts/integrations-cli/poetry.lock | 190 ++++++++++++++++++++++ scripts/integrations-cli/pyproject.toml | 21 +++ scripts/integrations-cli/requirements.txt | 12 -- 3 files changed, 211 insertions(+), 12 deletions(-) create mode 100644 scripts/integrations-cli/poetry.lock create mode 100644 scripts/integrations-cli/pyproject.toml delete mode 100644 scripts/integrations-cli/requirements.txt diff --git a/scripts/integrations-cli/poetry.lock b/scripts/integrations-cli/poetry.lock new file mode 100644 index 000000000..115ff3a0e --- /dev/null +++ b/scripts/integrations-cli/poetry.lock @@ -0,0 +1,190 @@ +[[package]] +name = "attrs" +version = "22.2.0" +description = "Classes Without Boilerplate" +category = "main" +optional = false +python-versions = ">=3.6" + +[package.extras] +cov = ["attrs", "coverage-enable-subprocess", "coverage[toml] (>=5.3)"] +dev = ["attrs"] +docs = ["furo", "sphinx", "myst-parser", "zope.interface", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier"] +tests = ["attrs", "zope.interface"] +tests-no-zope = ["hypothesis", "pympler", "pytest (>=4.3.0)", "pytest-xdist", "cloudpickle", "mypy (>=0.971,<0.990)", "pytest-mypy-plugins"] +tests_no_zope = ["hypothesis", "pympler", "pytest (>=4.3.0)", "pytest-xdist", "cloudpickle", "mypy (>=0.971,<0.990)", "pytest-mypy-plugins"] + +[[package]] +name = "black" +version = "23.3.0" +description = "The uncompromising code formatter." +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +click = ">=8.0.0" +mypy-extensions = ">=0.4.3" +packaging = ">=22.0" +pathspec = ">=0.9.0" +platformdirs = ">=2" +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} + +[package.extras] +colorama = ["colorama (>=0.4.3)"] +d = ["aiohttp (>=3.7.4)"] +jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] +uvloop = ["uvloop (>=0.15.2)"] + +[[package]] +name = "click" +version = "8.1.3" +description = "Composable command line interface toolkit" +category = "main" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} + +[[package]] +name = "colorama" +version = "0.4.6" +description = "Cross-platform colored terminal text." +category = "main" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" + +[[package]] +name = "isort" +version = "5.12.0" +description = "A Python utility / library to sort Python imports." +category = "dev" +optional = false +python-versions = ">=3.8.0" + +[package.extras] +colors = ["colorama (>=0.4.3)"] +requirements-deprecated-finder = ["pip-api", "pipreqs"] +pipfile-deprecated-finder = ["pip-shims (>=0.5.2)", "pipreqs", "requirementslib"] +plugins = ["setuptools"] + +[[package]] +name = "jsonschema" +version = "4.17.3" +description = "An implementation of JSON Schema validation for Python" +category = "main" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +attrs = ">=17.4.0" +pyrsistent = ">=0.14.0,<0.17.0 || >0.17.0,<0.17.1 || >0.17.1,<0.17.2 || >0.17.2" + +[package.extras] +format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"] +format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "uri-template", "webcolors (>=1.11)"] + +[[package]] +name = "mypy-extensions" +version = "1.0.0" +description = "Type system extensions for programs checked with the mypy type checker." +category = "dev" +optional = false +python-versions = ">=3.5" + +[[package]] +name = "packaging" +version = "23.0" +description = "Core utilities for Python packages" +category = "dev" +optional = false +python-versions = ">=3.7" + +[[package]] +name = "pathspec" +version = "0.11.1" +description = "Utility library for gitignore style pattern matching of file paths." +category = "dev" +optional = false +python-versions = ">=3.7" + +[[package]] +name = "platformdirs" +version = "3.2.0" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.extras] +docs = ["furo (>=2022.12.7)", "proselint (>=0.13)", "sphinx-autodoc-typehints (>=1.22,!=1.23.4)", "sphinx (>=6.1.3)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest-cov (>=4)", "pytest-mock (>=3.10)", "pytest (>=7.2.2)"] + +[[package]] +name = "pyrsistent" +version = "0.19.3" +description = "Persistent/Functional/Immutable data structures" +category = "main" +optional = false +python-versions = ">=3.7" + +[[package]] +name = "returns" +version = "0.19.0" +description = "Make your functions return something meaningful, typed, and safe!" +category = "main" +optional = false +python-versions = ">=3.7,<4.0" + +[package.dependencies] +typing-extensions = ">=4.0,<5.0" + +[[package]] +name = "termcolor" +version = "2.2.0" +description = "ANSI color formatting for output in terminal" +category = "main" +optional = false +python-versions = ">=3.7" + +[package.extras] +tests = ["pytest", "pytest-cov"] + +[[package]] +name = "tomli" +version = "2.0.1" +description = "A lil' TOML parser" +category = "dev" +optional = false +python-versions = ">=3.7" + +[[package]] +name = "typing-extensions" +version = "4.5.0" +description = "Backported and Experimental Type Hints for Python 3.7+" +category = "main" +optional = false +python-versions = ">=3.7" + +[metadata] +lock-version = "1.1" +python-versions = "^3.10" +content-hash = "5f8d3b96938e057449c63b661fad651af3c649cddf8f511134006c83b0151823" + +[metadata.files] +attrs = [] +black = [] +click = [] +colorama = [] +isort = [] +jsonschema = [] +mypy-extensions = [] +packaging = [] +pathspec = [] +platformdirs = [] +pyrsistent = [] +returns = [] +termcolor = [] +tomli = [] +typing-extensions = [] diff --git a/scripts/integrations-cli/pyproject.toml b/scripts/integrations-cli/pyproject.toml new file mode 100644 index 000000000..3d6c695ef --- /dev/null +++ b/scripts/integrations-cli/pyproject.toml @@ -0,0 +1,21 @@ +[tool.poetry] +name = "integrations-cli" +version = "0.1.0" +description = "CLI for managing OpenSearch Integrations" +authors = ["Simeon Widdis "] +license = "Apache-2.0" + +[tool.poetry.dependencies] +python = "^3.10" +click = "^8.1.3" +returns = "^0.19.0" +termcolor = "^2.2.0" +jsonschema = "^4.17.3" + +[tool.poetry.dev-dependencies] +black = "^23.3.0" +isort = "^5.12.0" + +[build-system] +requires = ["poetry-core>=1.0.0"] +build-backend = "poetry.core.masonry.api" diff --git a/scripts/integrations-cli/requirements.txt b/scripts/integrations-cli/requirements.txt deleted file mode 100644 index 906ddc9bd..000000000 --- a/scripts/integrations-cli/requirements.txt +++ /dev/null @@ -1,12 +0,0 @@ -attrs==22.2.0 -black==23.1.0 -click==8.1.3 -isort==5.12.0 -jsonschema==4.17.3 -mypy-extensions==1.0.0 -packaging==23.0 -pathspec==0.11.1 -platformdirs==3.1.1 -pyrsistent==0.19.3 -termcolor==2.2.0 -tomli==2.0.1 From 3c11c473b6a0ab386dd9f142038f7f210a71decd Mon Sep 17 00:00:00 2001 From: Simeon Widdis Date: Fri, 31 Mar 2023 15:15:49 -0700 Subject: [PATCH 06/40] Use returns Result for validation Signed-off-by: Simeon Widdis --- scripts/integrations-cli/helpers/constants.py | 4 +- scripts/integrations-cli/helpers/create.py | 6 +-- scripts/integrations-cli/helpers/validate.py | 23 +++++---- scripts/integrations-cli/integrations-cli.py | 48 +++++++------------ scripts/integrations-cli/pyproject.toml | 6 +++ .../integrations-cli/tests/test_validate.py | 17 ++++--- 6 files changed, 53 insertions(+), 51 deletions(-) diff --git a/scripts/integrations-cli/helpers/constants.py b/scripts/integrations-cli/helpers/constants.py index 446619a2e..90d56393c 100644 --- a/scripts/integrations-cli/helpers/constants.py +++ b/scripts/integrations-cli/helpers/constants.py @@ -19,7 +19,9 @@ # For now, assume we're running in the current relative directory if os.path.isdir(_SCHEMA_ROOT): - for filename in glob.glob(os.path.join(_SCHEMA_ROOT, "**/*.schema"), recursive=True): + for filename in glob.glob( + os.path.join(_SCHEMA_ROOT, "**/*.schema"), recursive=True + ): schema_name = os.path.split(filename)[1] with open(filename, "r") as schema_file: SCHEMAS[schema_name] = json.load(schema_file) diff --git a/scripts/integrations-cli/helpers/create.py b/scripts/integrations-cli/helpers/create.py index b7e25c33a..f4e6e9d2e 100644 --- a/scripts/integrations-cli/helpers/create.py +++ b/scripts/integrations-cli/helpers/create.py @@ -21,7 +21,7 @@ def with_path(self, path: str) -> "IntegrationBuilder": self.path = path self.config["repository"]["url"] = f"file://{path}" return self - + def with_schema_version(self, version: str) -> "IntegrationBuilder": if not re.match(r"^\d+\.\d+\.\d+", version): raise ValueError("Invalid version") @@ -34,10 +34,10 @@ def with_resource_version(self, version: str) -> "IntegrationBuilder": def with_description(self, desc: str) -> "IntegrationBuilder": self.config["description"] = desc - + def with_catalog(self, catalog: str) -> "IntegrationBuilder": self.config["catalog"] = catalog - + def with_repository(self, repo_url: str) -> "IntegrationBuilder": if not parse.urlparse(repo_url): raise ValueError("Invalid URL") diff --git a/scripts/integrations-cli/helpers/validate.py b/scripts/integrations-cli/helpers/validate.py index dd9fd3411..bb10d8fc6 100644 --- a/scripts/integrations-cli/helpers/validate.py +++ b/scripts/integrations-cli/helpers/validate.py @@ -1,13 +1,20 @@ -import logging - +from returns.result import Result, Failure, safe import jsonschema from .constants import SCHEMAS -def validate_config(config: dict) -> dict: - if "integration.schema" in SCHEMAS: - jsonschema.validate(instance=config, schema=SCHEMAS["integration.schema"]) - else: - raise ValueError("integration.schema does not exist") - return config +@safe(exceptions=( + jsonschema.exceptions.ValidationError, + jsonschema.exceptions.SchemaError, +)) +def validate_instance(instance: dict, schema: dict) -> dict: + jsonschema.validate(instance, schema) + return instance + + +def validate_config(config: dict) -> Result[dict, Exception]: + try: + return validate_instance(config, SCHEMAS["integration.schema"]) + except KeyError as err: + return Failure(err) diff --git a/scripts/integrations-cli/integrations-cli.py b/scripts/integrations-cli/integrations-cli.py index 4cdc784e7..b5913ab6a 100644 --- a/scripts/integrations-cli/integrations-cli.py +++ b/scripts/integrations-cli/integrations-cli.py @@ -14,12 +14,16 @@ @click.group() def integrations_cli(): """Create and maintain Integrations for the OpenSearch Integrations Plugin.""" - pass -def do_add_component(_builder: helpers.IntegrationBuilder): +def do_add_component(_builder: helpers.IntegrationBuilder) -> bool: + """Start an interactive session for """ click.echo("Interactive component definition is work-in-progress. Sorry!") - return "n" + return click.prompt( + "Configure another component? (y/n)", + type=click.Choice(["y", "n"], False), + show_choices=False, + ) == "y" @integrations_cli.command() @@ -35,30 +39,25 @@ def create(name: str): for subdir in ["assets", "info", "samples", "schema", "test"]: os.makedirs(os.path.join(integration_path, subdir)) builder = helpers.IntegrationBuilder().with_name(name).with_path(integration_path) - click.prompt( - "Schema version", default="1.0.0", type=builder.with_schema_version - ) - click.prompt( - "Resource version", type=builder.with_resource_version - ) - click.prompt( - "Integration description", default="", type=builder.with_description + click.prompt("Schema version", default="1.0.0", type=builder.with_schema_version) + click.prompt("Resource version", type=builder.with_resource_version) + click.prompt("Integration description", default="", type=builder.with_description) + builder.with_catalog( + click.prompt( + "Integration catalog", type=click.Choice(["observability", "security"]) + ) ) - builder.with_catalog(click.prompt( - "Integration catalog", - type=click.Choice(["observability", "security"]) - )) click.prompt( "Integration Repository URL", default="file://" + integration_path, - type=builder.with_repository + type=builder.with_repository, ) add_component = click.prompt( "Would you like to configure components interactively? (y/n)", type=click.Choice(["y", "n"], False), - show_choices=False - ) - while add_component == "y": + show_choices=False, + ) == "y" + while add_component: add_component = do_add_component(builder) builder.build() click.echo(colored(f"Integration created at '{integration_path}'", "green")) @@ -109,16 +108,5 @@ def package(name: str): click.echo(colored(f"Packaged integration as '{artifact_path}'", "green")) -@integrations_cli.command() -@click.argument("name") -@click.argument("opensearch_url", default="http://localhost:9200/") -def upload(name: str, opensearch_url: str): - url = parse.urlparse(opensearch_url) - if not url: - click.echo(colored("Invalid URL", "red")) - return - print(url) - - if __name__ == "__main__": integrations_cli() diff --git a/scripts/integrations-cli/pyproject.toml b/scripts/integrations-cli/pyproject.toml index 3d6c695ef..ccc567ff6 100644 --- a/scripts/integrations-cli/pyproject.toml +++ b/scripts/integrations-cli/pyproject.toml @@ -5,6 +5,12 @@ description = "CLI for managing OpenSearch Integrations" authors = ["Simeon Widdis "] license = "Apache-2.0" +[tool.isort] +profile = "black" + +[tool.pylint] +disable = "missing-function-docstring" + [tool.poetry.dependencies] python = "^3.10" click = "^8.1.3" diff --git a/scripts/integrations-cli/tests/test_validate.py b/scripts/integrations-cli/tests/test_validate.py index 973b85cee..3d8390202 100644 --- a/scripts/integrations-cli/tests/test_validate.py +++ b/scripts/integrations-cli/tests/test_validate.py @@ -5,6 +5,7 @@ import helpers.constants as constants import helpers.validate as validate +from returns.pipeline import is_successful class TestSchemas(unittest.TestCase): @@ -13,21 +14,19 @@ def test_config_schema_is_valid(self): jsonschema.Draft6Validator.check_schema(config_schema) -class TestDefaults(unittest.TestCase): - def test_default_config_is_valid(self): - config_schema = constants.SCHEMAS["integration.schema"] - jsonschema.validate(constants.DEFAULT_CONFIG, config_schema) +class TestConfigValidations(unittest.TestCase): + """Test validations pertaining to config objects""" + def test_default_config_is_valid(self): + config = deepcopy(constants.DEFAULT_CONFIG) + assert is_successful(validate.validate_config(config)) -class TestFailingValidations(unittest.TestCase): def test_default_with_no_name_is_invalid(self): config = deepcopy(constants.DEFAULT_CONFIG) del config["template-name"] - with self.assertRaises(jsonschema.exceptions.ValidationError): - validate.validate_config(config) + assert not is_successful(validate.validate_config(config)) def test_default_with_integer_description_is_invalid(self): config = deepcopy(constants.DEFAULT_CONFIG) config["description"] = 0 - with self.assertRaises(jsonschema.exceptions.ValidationError): - validate.validate_config(config) + assert not is_successful(validate.validate_config(config)) From 1766927aa61d3ba35976bde32d945a8166dd987f Mon Sep 17 00:00:00 2001 From: Simeon Widdis Date: Fri, 31 Mar 2023 15:24:07 -0700 Subject: [PATCH 07/40] Pylint maintenance Signed-off-by: Simeon Widdis --- scripts/integrations-cli/helpers/validate.py | 10 +- scripts/integrations-cli/integrations-cli.py | 29 +- scripts/integrations-cli/poetry.lock | 691 +++++++++++++----- scripts/integrations-cli/pyproject.toml | 3 +- .../integrations-cli/tests/test_validate.py | 2 - 5 files changed, 526 insertions(+), 209 deletions(-) diff --git a/scripts/integrations-cli/helpers/validate.py b/scripts/integrations-cli/helpers/validate.py index bb10d8fc6..50d2166a3 100644 --- a/scripts/integrations-cli/helpers/validate.py +++ b/scripts/integrations-cli/helpers/validate.py @@ -4,10 +4,12 @@ from .constants import SCHEMAS -@safe(exceptions=( - jsonschema.exceptions.ValidationError, - jsonschema.exceptions.SchemaError, -)) +@safe( + exceptions=( + jsonschema.exceptions.ValidationError, + jsonschema.exceptions.SchemaError, + ) +) def validate_instance(instance: dict, schema: dict) -> dict: jsonschema.validate(instance, schema) return instance diff --git a/scripts/integrations-cli/integrations-cli.py b/scripts/integrations-cli/integrations-cli.py index b5913ab6a..00a44df9f 100644 --- a/scripts/integrations-cli/integrations-cli.py +++ b/scripts/integrations-cli/integrations-cli.py @@ -1,7 +1,6 @@ #!./venv/bin/python3 import json import os -from urllib import parse import zipfile import click @@ -17,13 +16,16 @@ def integrations_cli(): def do_add_component(_builder: helpers.IntegrationBuilder) -> bool: - """Start an interactive session for """ + """Start an interactive session for""" click.echo("Interactive component definition is work-in-progress. Sorry!") - return click.prompt( - "Configure another component? (y/n)", - type=click.Choice(["y", "n"], False), - show_choices=False, - ) == "y" + return ( + click.prompt( + "Configure another component? (y/n)", + type=click.Choice(["y", "n"], False), + show_choices=False, + ) + == "y" + ) @integrations_cli.command() @@ -52,11 +54,14 @@ def create(name: str): default="file://" + integration_path, type=builder.with_repository, ) - add_component = click.prompt( - "Would you like to configure components interactively? (y/n)", - type=click.Choice(["y", "n"], False), - show_choices=False, - ) == "y" + add_component = ( + click.prompt( + "Would you like to configure components interactively? (y/n)", + type=click.Choice(["y", "n"], False), + show_choices=False, + ) + == "y" + ) while add_component: add_component = do_add_component(builder) builder.build() diff --git a/scripts/integrations-cli/poetry.lock b/scripts/integrations-cli/poetry.lock index 115ff3a0e..4e45c5102 100644 --- a/scripts/integrations-cli/poetry.lock +++ b/scripts/integrations-cli/poetry.lock @@ -1,190 +1,501 @@ -[[package]] -name = "attrs" -version = "22.2.0" -description = "Classes Without Boilerplate" -category = "main" -optional = false -python-versions = ">=3.6" - -[package.extras] -cov = ["attrs", "coverage-enable-subprocess", "coverage[toml] (>=5.3)"] -dev = ["attrs"] -docs = ["furo", "sphinx", "myst-parser", "zope.interface", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier"] -tests = ["attrs", "zope.interface"] -tests-no-zope = ["hypothesis", "pympler", "pytest (>=4.3.0)", "pytest-xdist", "cloudpickle", "mypy (>=0.971,<0.990)", "pytest-mypy-plugins"] -tests_no_zope = ["hypothesis", "pympler", "pytest (>=4.3.0)", "pytest-xdist", "cloudpickle", "mypy (>=0.971,<0.990)", "pytest-mypy-plugins"] - -[[package]] -name = "black" -version = "23.3.0" -description = "The uncompromising code formatter." -category = "dev" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -click = ">=8.0.0" -mypy-extensions = ">=0.4.3" -packaging = ">=22.0" -pathspec = ">=0.9.0" -platformdirs = ">=2" -tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} - -[package.extras] -colorama = ["colorama (>=0.4.3)"] -d = ["aiohttp (>=3.7.4)"] -jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] -uvloop = ["uvloop (>=0.15.2)"] - -[[package]] -name = "click" -version = "8.1.3" -description = "Composable command line interface toolkit" -category = "main" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -colorama = {version = "*", markers = "platform_system == \"Windows\""} - -[[package]] -name = "colorama" -version = "0.4.6" -description = "Cross-platform colored terminal text." -category = "main" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" - -[[package]] -name = "isort" -version = "5.12.0" -description = "A Python utility / library to sort Python imports." -category = "dev" -optional = false -python-versions = ">=3.8.0" - -[package.extras] -colors = ["colorama (>=0.4.3)"] -requirements-deprecated-finder = ["pip-api", "pipreqs"] -pipfile-deprecated-finder = ["pip-shims (>=0.5.2)", "pipreqs", "requirementslib"] -plugins = ["setuptools"] - -[[package]] -name = "jsonschema" -version = "4.17.3" -description = "An implementation of JSON Schema validation for Python" -category = "main" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -attrs = ">=17.4.0" -pyrsistent = ">=0.14.0,<0.17.0 || >0.17.0,<0.17.1 || >0.17.1,<0.17.2 || >0.17.2" - -[package.extras] -format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"] -format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "uri-template", "webcolors (>=1.11)"] - -[[package]] -name = "mypy-extensions" -version = "1.0.0" -description = "Type system extensions for programs checked with the mypy type checker." -category = "dev" -optional = false -python-versions = ">=3.5" - -[[package]] -name = "packaging" -version = "23.0" -description = "Core utilities for Python packages" -category = "dev" -optional = false -python-versions = ">=3.7" - -[[package]] -name = "pathspec" -version = "0.11.1" -description = "Utility library for gitignore style pattern matching of file paths." -category = "dev" -optional = false -python-versions = ">=3.7" - -[[package]] -name = "platformdirs" -version = "3.2.0" -description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." -category = "dev" -optional = false -python-versions = ">=3.7" - -[package.extras] -docs = ["furo (>=2022.12.7)", "proselint (>=0.13)", "sphinx-autodoc-typehints (>=1.22,!=1.23.4)", "sphinx (>=6.1.3)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest-cov (>=4)", "pytest-mock (>=3.10)", "pytest (>=7.2.2)"] - -[[package]] -name = "pyrsistent" -version = "0.19.3" -description = "Persistent/Functional/Immutable data structures" -category = "main" -optional = false -python-versions = ">=3.7" - -[[package]] -name = "returns" -version = "0.19.0" -description = "Make your functions return something meaningful, typed, and safe!" -category = "main" -optional = false -python-versions = ">=3.7,<4.0" - -[package.dependencies] -typing-extensions = ">=4.0,<5.0" - -[[package]] -name = "termcolor" -version = "2.2.0" -description = "ANSI color formatting for output in terminal" -category = "main" -optional = false -python-versions = ">=3.7" - -[package.extras] -tests = ["pytest", "pytest-cov"] - -[[package]] -name = "tomli" -version = "2.0.1" -description = "A lil' TOML parser" -category = "dev" -optional = false -python-versions = ">=3.7" - -[[package]] -name = "typing-extensions" -version = "4.5.0" -description = "Backported and Experimental Type Hints for Python 3.7+" -category = "main" -optional = false -python-versions = ">=3.7" - -[metadata] -lock-version = "1.1" -python-versions = "^3.10" -content-hash = "5f8d3b96938e057449c63b661fad651af3c649cddf8f511134006c83b0151823" - -[metadata.files] -attrs = [] -black = [] -click = [] -colorama = [] -isort = [] -jsonschema = [] -mypy-extensions = [] -packaging = [] -pathspec = [] -platformdirs = [] -pyrsistent = [] -returns = [] -termcolor = [] -tomli = [] -typing-extensions = [] +# This file is automatically @generated by Poetry 1.4.1 and should not be changed by hand. + +[[package]] +name = "astroid" +version = "2.15.1" +description = "An abstract syntax tree for Python with inference support." +category = "dev" +optional = false +python-versions = ">=3.7.2" +files = [ + {file = "astroid-2.15.1-py3-none-any.whl", hash = "sha256:89860bda98fe2bbd1f5d262229be7629d778ce280de68d95d4a73d1f592ad268"}, + {file = "astroid-2.15.1.tar.gz", hash = "sha256:af4e0aff46e2868218502789898269ed95b663fba49e65d91c1e09c966266c34"}, +] + +[package.dependencies] +lazy-object-proxy = ">=1.4.0" +typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.11\""} +wrapt = [ + {version = ">=1.11,<2", markers = "python_version < \"3.11\""}, + {version = ">=1.14,<2", markers = "python_version >= \"3.11\""}, +] + +[[package]] +name = "attrs" +version = "22.2.0" +description = "Classes Without Boilerplate" +category = "main" +optional = false +python-versions = ">=3.6" +files = [ + {file = "attrs-22.2.0-py3-none-any.whl", hash = "sha256:29e95c7f6778868dbd49170f98f8818f78f3dc5e0e37c0b1f474e3561b240836"}, + {file = "attrs-22.2.0.tar.gz", hash = "sha256:c9227bfc2f01993c03f68db37d1d15c9690188323c067c641f1a35ca58185f99"}, +] + +[package.extras] +cov = ["attrs[tests]", "coverage-enable-subprocess", "coverage[toml] (>=5.3)"] +dev = ["attrs[docs,tests]"] +docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope.interface"] +tests = ["attrs[tests-no-zope]", "zope.interface"] +tests-no-zope = ["cloudpickle", "cloudpickle", "hypothesis", "hypothesis", "mypy (>=0.971,<0.990)", "mypy (>=0.971,<0.990)", "pympler", "pympler", "pytest (>=4.3.0)", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-mypy-plugins", "pytest-xdist[psutil]", "pytest-xdist[psutil]"] + +[[package]] +name = "black" +version = "23.3.0" +description = "The uncompromising code formatter." +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "black-23.3.0-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:0945e13506be58bf7db93ee5853243eb368ace1c08a24c65ce108986eac65915"}, + {file = "black-23.3.0-cp310-cp310-macosx_10_16_universal2.whl", hash = "sha256:67de8d0c209eb5b330cce2469503de11bca4085880d62f1628bd9972cc3366b9"}, + {file = "black-23.3.0-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:7c3eb7cea23904399866c55826b31c1f55bbcd3890ce22ff70466b907b6775c2"}, + {file = "black-23.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:32daa9783106c28815d05b724238e30718f34155653d4d6e125dc7daec8e260c"}, + {file = "black-23.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:35d1381d7a22cc5b2be2f72c7dfdae4072a3336060635718cc7e1ede24221d6c"}, + {file = "black-23.3.0-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:a8a968125d0a6a404842fa1bf0b349a568634f856aa08ffaff40ae0dfa52e7c6"}, + {file = "black-23.3.0-cp311-cp311-macosx_10_16_universal2.whl", hash = "sha256:c7ab5790333c448903c4b721b59c0d80b11fe5e9803d8703e84dcb8da56fec1b"}, + {file = "black-23.3.0-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:a6f6886c9869d4daae2d1715ce34a19bbc4b95006d20ed785ca00fa03cba312d"}, + {file = "black-23.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f3c333ea1dd6771b2d3777482429864f8e258899f6ff05826c3a4fcc5ce3f70"}, + {file = "black-23.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:11c410f71b876f961d1de77b9699ad19f939094c3a677323f43d7a29855fe326"}, + {file = "black-23.3.0-cp37-cp37m-macosx_10_16_x86_64.whl", hash = "sha256:1d06691f1eb8de91cd1b322f21e3bfc9efe0c7ca1f0e1eb1db44ea367dff656b"}, + {file = "black-23.3.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50cb33cac881766a5cd9913e10ff75b1e8eb71babf4c7104f2e9c52da1fb7de2"}, + {file = "black-23.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:e114420bf26b90d4b9daa597351337762b63039752bdf72bf361364c1aa05925"}, + {file = "black-23.3.0-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:48f9d345675bb7fbc3dd85821b12487e1b9a75242028adad0333ce36ed2a6d27"}, + {file = "black-23.3.0-cp38-cp38-macosx_10_16_universal2.whl", hash = "sha256:714290490c18fb0126baa0fca0a54ee795f7502b44177e1ce7624ba1c00f2331"}, + {file = "black-23.3.0-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:064101748afa12ad2291c2b91c960be28b817c0c7eaa35bec09cc63aa56493c5"}, + {file = "black-23.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:562bd3a70495facf56814293149e51aa1be9931567474993c7942ff7d3533961"}, + {file = "black-23.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:e198cf27888ad6f4ff331ca1c48ffc038848ea9f031a3b40ba36aced7e22f2c8"}, + {file = "black-23.3.0-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:3238f2aacf827d18d26db07524e44741233ae09a584273aa059066d644ca7b30"}, + {file = "black-23.3.0-cp39-cp39-macosx_10_16_universal2.whl", hash = "sha256:f0bd2f4a58d6666500542b26354978218a9babcdc972722f4bf90779524515f3"}, + {file = "black-23.3.0-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:92c543f6854c28a3c7f39f4d9b7694f9a6eb9d3c5e2ece488c327b6e7ea9b266"}, + {file = "black-23.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a150542a204124ed00683f0db1f5cf1c2aaaa9cc3495b7a3b5976fb136090ab"}, + {file = "black-23.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:6b39abdfb402002b8a7d030ccc85cf5afff64ee90fa4c5aebc531e3ad0175ddb"}, + {file = "black-23.3.0-py3-none-any.whl", hash = "sha256:ec751418022185b0c1bb7d7736e6933d40bbb14c14a0abcf9123d1b159f98dd4"}, + {file = "black-23.3.0.tar.gz", hash = "sha256:1c7b8d606e728a41ea1ccbd7264677e494e87cf630e399262ced92d4a8dac940"}, +] + +[package.dependencies] +click = ">=8.0.0" +mypy-extensions = ">=0.4.3" +packaging = ">=22.0" +pathspec = ">=0.9.0" +platformdirs = ">=2" +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} + +[package.extras] +colorama = ["colorama (>=0.4.3)"] +d = ["aiohttp (>=3.7.4)"] +jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] +uvloop = ["uvloop (>=0.15.2)"] + +[[package]] +name = "click" +version = "8.1.3" +description = "Composable command line interface toolkit" +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"}, + {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} + +[[package]] +name = "colorama" +version = "0.4.6" +description = "Cross-platform colored terminal text." +category = "main" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +files = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] + +[[package]] +name = "dill" +version = "0.3.6" +description = "serialize all of python" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "dill-0.3.6-py3-none-any.whl", hash = "sha256:a07ffd2351b8c678dfc4a856a3005f8067aea51d6ba6c700796a4d9e280f39f0"}, + {file = "dill-0.3.6.tar.gz", hash = "sha256:e5db55f3687856d8fbdab002ed78544e1c4559a130302693d839dfe8f93f2373"}, +] + +[package.extras] +graph = ["objgraph (>=1.7.2)"] + +[[package]] +name = "isort" +version = "5.12.0" +description = "A Python utility / library to sort Python imports." +category = "dev" +optional = false +python-versions = ">=3.8.0" +files = [ + {file = "isort-5.12.0-py3-none-any.whl", hash = "sha256:f84c2818376e66cf843d497486ea8fed8700b340f308f076c6fb1229dff318b6"}, + {file = "isort-5.12.0.tar.gz", hash = "sha256:8bef7dde241278824a6d83f44a544709b065191b95b6e50894bdc722fcba0504"}, +] + +[package.extras] +colors = ["colorama (>=0.4.3)"] +pipfile-deprecated-finder = ["pip-shims (>=0.5.2)", "pipreqs", "requirementslib"] +plugins = ["setuptools"] +requirements-deprecated-finder = ["pip-api", "pipreqs"] + +[[package]] +name = "jsonschema" +version = "4.17.3" +description = "An implementation of JSON Schema validation for Python" +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "jsonschema-4.17.3-py3-none-any.whl", hash = "sha256:a870ad254da1a8ca84b6a2905cac29d265f805acc57af304784962a2aa6508f6"}, + {file = "jsonschema-4.17.3.tar.gz", hash = "sha256:0f864437ab8b6076ba6707453ef8f98a6a0d512a80e93f8abdb676f737ecb60d"}, +] + +[package.dependencies] +attrs = ">=17.4.0" +pyrsistent = ">=0.14.0,<0.17.0 || >0.17.0,<0.17.1 || >0.17.1,<0.17.2 || >0.17.2" + +[package.extras] +format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"] +format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "uri-template", "webcolors (>=1.11)"] + +[[package]] +name = "lazy-object-proxy" +version = "1.9.0" +description = "A fast and thorough lazy object proxy." +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "lazy-object-proxy-1.9.0.tar.gz", hash = "sha256:659fb5809fa4629b8a1ac5106f669cfc7bef26fbb389dda53b3e010d1ac4ebae"}, + {file = "lazy_object_proxy-1.9.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b40387277b0ed2d0602b8293b94d7257e17d1479e257b4de114ea11a8cb7f2d7"}, + {file = "lazy_object_proxy-1.9.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8c6cfb338b133fbdbc5cfaa10fe3c6aeea827db80c978dbd13bc9dd8526b7d4"}, + {file = "lazy_object_proxy-1.9.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:721532711daa7db0d8b779b0bb0318fa87af1c10d7fe5e52ef30f8eff254d0cd"}, + {file = "lazy_object_proxy-1.9.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:66a3de4a3ec06cd8af3f61b8e1ec67614fbb7c995d02fa224813cb7afefee701"}, + {file = "lazy_object_proxy-1.9.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:1aa3de4088c89a1b69f8ec0dcc169aa725b0ff017899ac568fe44ddc1396df46"}, + {file = "lazy_object_proxy-1.9.0-cp310-cp310-win32.whl", hash = "sha256:f0705c376533ed2a9e5e97aacdbfe04cecd71e0aa84c7c0595d02ef93b6e4455"}, + {file = "lazy_object_proxy-1.9.0-cp310-cp310-win_amd64.whl", hash = "sha256:ea806fd4c37bf7e7ad82537b0757999264d5f70c45468447bb2b91afdbe73a6e"}, + {file = "lazy_object_proxy-1.9.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:946d27deaff6cf8452ed0dba83ba38839a87f4f7a9732e8f9fd4107b21e6ff07"}, + {file = "lazy_object_proxy-1.9.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79a31b086e7e68b24b99b23d57723ef7e2c6d81ed21007b6281ebcd1688acb0a"}, + {file = "lazy_object_proxy-1.9.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f699ac1c768270c9e384e4cbd268d6e67aebcfae6cd623b4d7c3bfde5a35db59"}, + {file = "lazy_object_proxy-1.9.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bfb38f9ffb53b942f2b5954e0f610f1e721ccebe9cce9025a38c8ccf4a5183a4"}, + {file = "lazy_object_proxy-1.9.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:189bbd5d41ae7a498397287c408617fe5c48633e7755287b21d741f7db2706a9"}, + {file = "lazy_object_proxy-1.9.0-cp311-cp311-win32.whl", hash = "sha256:81fc4d08b062b535d95c9ea70dbe8a335c45c04029878e62d744bdced5141586"}, + {file = "lazy_object_proxy-1.9.0-cp311-cp311-win_amd64.whl", hash = "sha256:f2457189d8257dd41ae9b434ba33298aec198e30adf2dcdaaa3a28b9994f6adb"}, + {file = "lazy_object_proxy-1.9.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:d9e25ef10a39e8afe59a5c348a4dbf29b4868ab76269f81ce1674494e2565a6e"}, + {file = "lazy_object_proxy-1.9.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cbf9b082426036e19c6924a9ce90c740a9861e2bdc27a4834fd0a910742ac1e8"}, + {file = "lazy_object_proxy-1.9.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f5fa4a61ce2438267163891961cfd5e32ec97a2c444e5b842d574251ade27d2"}, + {file = "lazy_object_proxy-1.9.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:8fa02eaab317b1e9e03f69aab1f91e120e7899b392c4fc19807a8278a07a97e8"}, + {file = "lazy_object_proxy-1.9.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e7c21c95cae3c05c14aafffe2865bbd5e377cfc1348c4f7751d9dc9a48ca4bda"}, + {file = "lazy_object_proxy-1.9.0-cp37-cp37m-win32.whl", hash = "sha256:f12ad7126ae0c98d601a7ee504c1122bcef553d1d5e0c3bfa77b16b3968d2734"}, + {file = "lazy_object_proxy-1.9.0-cp37-cp37m-win_amd64.whl", hash = "sha256:edd20c5a55acb67c7ed471fa2b5fb66cb17f61430b7a6b9c3b4a1e40293b1671"}, + {file = "lazy_object_proxy-1.9.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2d0daa332786cf3bb49e10dc6a17a52f6a8f9601b4cf5c295a4f85854d61de63"}, + {file = "lazy_object_proxy-1.9.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cd077f3d04a58e83d04b20e334f678c2b0ff9879b9375ed107d5d07ff160171"}, + {file = "lazy_object_proxy-1.9.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:660c94ea760b3ce47d1855a30984c78327500493d396eac4dfd8bd82041b22be"}, + {file = "lazy_object_proxy-1.9.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:212774e4dfa851e74d393a2370871e174d7ff0ebc980907723bb67d25c8a7c30"}, + {file = "lazy_object_proxy-1.9.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:f0117049dd1d5635bbff65444496c90e0baa48ea405125c088e93d9cf4525b11"}, + {file = "lazy_object_proxy-1.9.0-cp38-cp38-win32.whl", hash = "sha256:0a891e4e41b54fd5b8313b96399f8b0e173bbbfc03c7631f01efbe29bb0bcf82"}, + {file = "lazy_object_proxy-1.9.0-cp38-cp38-win_amd64.whl", hash = "sha256:9990d8e71b9f6488e91ad25f322898c136b008d87bf852ff65391b004da5e17b"}, + {file = "lazy_object_proxy-1.9.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9e7551208b2aded9c1447453ee366f1c4070602b3d932ace044715d89666899b"}, + {file = "lazy_object_proxy-1.9.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f83ac4d83ef0ab017683d715ed356e30dd48a93746309c8f3517e1287523ef4"}, + {file = "lazy_object_proxy-1.9.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7322c3d6f1766d4ef1e51a465f47955f1e8123caee67dd641e67d539a534d006"}, + {file = "lazy_object_proxy-1.9.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:18b78ec83edbbeb69efdc0e9c1cb41a3b1b1ed11ddd8ded602464c3fc6020494"}, + {file = "lazy_object_proxy-1.9.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:09763491ce220c0299688940f8dc2c5d05fd1f45af1e42e636b2e8b2303e4382"}, + {file = "lazy_object_proxy-1.9.0-cp39-cp39-win32.whl", hash = "sha256:9090d8e53235aa280fc9239a86ae3ea8ac58eff66a705fa6aa2ec4968b95c821"}, + {file = "lazy_object_proxy-1.9.0-cp39-cp39-win_amd64.whl", hash = "sha256:db1c1722726f47e10e0b5fdbf15ac3b8adb58c091d12b3ab713965795036985f"}, +] + +[[package]] +name = "mccabe" +version = "0.7.0" +description = "McCabe checker, plugin for flake8" +category = "dev" +optional = false +python-versions = ">=3.6" +files = [ + {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, + {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, +] + +[[package]] +name = "mypy-extensions" +version = "1.0.0" +description = "Type system extensions for programs checked with the mypy type checker." +category = "dev" +optional = false +python-versions = ">=3.5" +files = [ + {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, + {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, +] + +[[package]] +name = "packaging" +version = "23.0" +description = "Core utilities for Python packages" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "packaging-23.0-py3-none-any.whl", hash = "sha256:714ac14496c3e68c99c29b00845f7a2b85f3bb6f1078fd9f72fd20f0570002b2"}, + {file = "packaging-23.0.tar.gz", hash = "sha256:b6ad297f8907de0fa2fe1ccbd26fdaf387f5f47c7275fedf8cce89f99446cf97"}, +] + +[[package]] +name = "pathspec" +version = "0.11.1" +description = "Utility library for gitignore style pattern matching of file paths." +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pathspec-0.11.1-py3-none-any.whl", hash = "sha256:d8af70af76652554bd134c22b3e8a1cc46ed7d91edcdd721ef1a0c51a84a5293"}, + {file = "pathspec-0.11.1.tar.gz", hash = "sha256:2798de800fa92780e33acca925945e9a19a133b715067cf165b8866c15a31687"}, +] + +[[package]] +name = "platformdirs" +version = "3.2.0" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "platformdirs-3.2.0-py3-none-any.whl", hash = "sha256:ebe11c0d7a805086e99506aa331612429a72ca7cd52a1f0d277dc4adc20cb10e"}, + {file = "platformdirs-3.2.0.tar.gz", hash = "sha256:d5b638ca397f25f979350ff789db335903d7ea010ab28903f57b27e1b16c2b08"}, +] + +[package.extras] +docs = ["furo (>=2022.12.7)", "proselint (>=0.13)", "sphinx (>=6.1.3)", "sphinx-autodoc-typehints (>=1.22,!=1.23.4)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.2.2)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"] + +[[package]] +name = "pylint" +version = "2.17.1" +description = "python code static checker" +category = "dev" +optional = false +python-versions = ">=3.7.2" +files = [ + {file = "pylint-2.17.1-py3-none-any.whl", hash = "sha256:8660a54e3f696243d644fca98f79013a959c03f979992c1ab59c24d3f4ec2700"}, + {file = "pylint-2.17.1.tar.gz", hash = "sha256:d4d009b0116e16845533bc2163493d6681846ac725eab8ca8014afb520178ddd"}, +] + +[package.dependencies] +astroid = ">=2.15.0,<=2.17.0-dev0" +colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} +dill = [ + {version = ">=0.2", markers = "python_version < \"3.11\""}, + {version = ">=0.3.6", markers = "python_version >= \"3.11\""}, +] +isort = ">=4.2.5,<6" +mccabe = ">=0.6,<0.8" +platformdirs = ">=2.2.0" +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} +tomlkit = ">=0.10.1" + +[package.extras] +spelling = ["pyenchant (>=3.2,<4.0)"] +testutils = ["gitpython (>3)"] + +[[package]] +name = "pyrsistent" +version = "0.19.3" +description = "Persistent/Functional/Immutable data structures" +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pyrsistent-0.19.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:20460ac0ea439a3e79caa1dbd560344b64ed75e85d8703943e0b66c2a6150e4a"}, + {file = "pyrsistent-0.19.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4c18264cb84b5e68e7085a43723f9e4c1fd1d935ab240ce02c0324a8e01ccb64"}, + {file = "pyrsistent-0.19.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4b774f9288dda8d425adb6544e5903f1fb6c273ab3128a355c6b972b7df39dcf"}, + {file = "pyrsistent-0.19.3-cp310-cp310-win32.whl", hash = "sha256:5a474fb80f5e0d6c9394d8db0fc19e90fa540b82ee52dba7d246a7791712f74a"}, + {file = "pyrsistent-0.19.3-cp310-cp310-win_amd64.whl", hash = "sha256:49c32f216c17148695ca0e02a5c521e28a4ee6c5089f97e34fe24163113722da"}, + {file = "pyrsistent-0.19.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f0774bf48631f3a20471dd7c5989657b639fd2d285b861237ea9e82c36a415a9"}, + {file = "pyrsistent-0.19.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3ab2204234c0ecd8b9368dbd6a53e83c3d4f3cab10ecaf6d0e772f456c442393"}, + {file = "pyrsistent-0.19.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e42296a09e83028b3476f7073fcb69ffebac0e66dbbfd1bd847d61f74db30f19"}, + {file = "pyrsistent-0.19.3-cp311-cp311-win32.whl", hash = "sha256:64220c429e42a7150f4bfd280f6f4bb2850f95956bde93c6fda1b70507af6ef3"}, + {file = "pyrsistent-0.19.3-cp311-cp311-win_amd64.whl", hash = "sha256:016ad1afadf318eb7911baa24b049909f7f3bb2c5b1ed7b6a8f21db21ea3faa8"}, + {file = "pyrsistent-0.19.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c4db1bd596fefd66b296a3d5d943c94f4fac5bcd13e99bffe2ba6a759d959a28"}, + {file = "pyrsistent-0.19.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aeda827381f5e5d65cced3024126529ddc4289d944f75e090572c77ceb19adbf"}, + {file = "pyrsistent-0.19.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:42ac0b2f44607eb92ae88609eda931a4f0dfa03038c44c772e07f43e738bcac9"}, + {file = "pyrsistent-0.19.3-cp37-cp37m-win32.whl", hash = "sha256:e8f2b814a3dc6225964fa03d8582c6e0b6650d68a232df41e3cc1b66a5d2f8d1"}, + {file = "pyrsistent-0.19.3-cp37-cp37m-win_amd64.whl", hash = "sha256:c9bb60a40a0ab9aba40a59f68214eed5a29c6274c83b2cc206a359c4a89fa41b"}, + {file = "pyrsistent-0.19.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:a2471f3f8693101975b1ff85ffd19bb7ca7dd7c38f8a81701f67d6b4f97b87d8"}, + {file = "pyrsistent-0.19.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc5d149f31706762c1f8bda2e8c4f8fead6e80312e3692619a75301d3dbb819a"}, + {file = "pyrsistent-0.19.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3311cb4237a341aa52ab8448c27e3a9931e2ee09561ad150ba94e4cfd3fc888c"}, + {file = "pyrsistent-0.19.3-cp38-cp38-win32.whl", hash = "sha256:f0e7c4b2f77593871e918be000b96c8107da48444d57005b6a6bc61fb4331b2c"}, + {file = "pyrsistent-0.19.3-cp38-cp38-win_amd64.whl", hash = "sha256:c147257a92374fde8498491f53ffa8f4822cd70c0d85037e09028e478cababb7"}, + {file = "pyrsistent-0.19.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:b735e538f74ec31378f5a1e3886a26d2ca6351106b4dfde376a26fc32a044edc"}, + {file = "pyrsistent-0.19.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99abb85579e2165bd8522f0c0138864da97847875ecbd45f3e7e2af569bfc6f2"}, + {file = "pyrsistent-0.19.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3a8cb235fa6d3fd7aae6a4f1429bbb1fec1577d978098da1252f0489937786f3"}, + {file = "pyrsistent-0.19.3-cp39-cp39-win32.whl", hash = "sha256:c74bed51f9b41c48366a286395c67f4e894374306b197e62810e0fdaf2364da2"}, + {file = "pyrsistent-0.19.3-cp39-cp39-win_amd64.whl", hash = "sha256:878433581fc23e906d947a6814336eee031a00e6defba224234169ae3d3d6a98"}, + {file = "pyrsistent-0.19.3-py3-none-any.whl", hash = "sha256:ccf0d6bd208f8111179f0c26fdf84ed7c3891982f2edaeae7422575f47e66b64"}, + {file = "pyrsistent-0.19.3.tar.gz", hash = "sha256:1a2994773706bbb4995c31a97bc94f1418314923bd1048c6d964837040376440"}, +] + +[[package]] +name = "returns" +version = "0.19.0" +description = "Make your functions return something meaningful, typed, and safe!" +category = "main" +optional = false +python-versions = ">=3.7,<4.0" +files = [ + {file = "returns-0.19.0-py3-none-any.whl", hash = "sha256:ae3ce9e5165d1218905291b4d5881b4e8a86ca478437bef3b0af1de8df57ec69"}, + {file = "returns-0.19.0.tar.gz", hash = "sha256:4544bb67849c1ef1bbf7823759d433a773959e5b77a8fd06d01fef6d060f2ac5"}, +] + +[package.dependencies] +typing-extensions = ">=4.0,<5.0" + +[[package]] +name = "termcolor" +version = "2.2.0" +description = "ANSI color formatting for output in terminal" +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "termcolor-2.2.0-py3-none-any.whl", hash = "sha256:91ddd848e7251200eac969846cbae2dacd7d71c2871e92733289e7e3666f48e7"}, + {file = "termcolor-2.2.0.tar.gz", hash = "sha256:dfc8ac3f350788f23b2947b3e6cfa5a53b630b612e6cd8965a015a776020b99a"}, +] + +[package.extras] +tests = ["pytest", "pytest-cov"] + +[[package]] +name = "tomli" +version = "2.0.1" +description = "A lil' TOML parser" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, + {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, +] + +[[package]] +name = "tomlkit" +version = "0.11.7" +description = "Style preserving TOML library" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "tomlkit-0.11.7-py3-none-any.whl", hash = "sha256:5325463a7da2ef0c6bbfefb62a3dc883aebe679984709aee32a317907d0a8d3c"}, + {file = "tomlkit-0.11.7.tar.gz", hash = "sha256:f392ef70ad87a672f02519f99967d28a4d3047133e2d1df936511465fbb3791d"}, +] + +[[package]] +name = "typing-extensions" +version = "4.5.0" +description = "Backported and Experimental Type Hints for Python 3.7+" +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "typing_extensions-4.5.0-py3-none-any.whl", hash = "sha256:fb33085c39dd998ac16d1431ebc293a8b3eedd00fd4a32de0ff79002c19511b4"}, + {file = "typing_extensions-4.5.0.tar.gz", hash = "sha256:5cb5f4a79139d699607b3ef622a1dedafa84e115ab0024e0d9c044a9479ca7cb"}, +] + +[[package]] +name = "wrapt" +version = "1.15.0" +description = "Module for decorators, wrappers and monkey patching." +category = "dev" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" +files = [ + {file = "wrapt-1.15.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:ca1cccf838cd28d5a0883b342474c630ac48cac5df0ee6eacc9c7290f76b11c1"}, + {file = "wrapt-1.15.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:e826aadda3cae59295b95343db8f3d965fb31059da7de01ee8d1c40a60398b29"}, + {file = "wrapt-1.15.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:5fc8e02f5984a55d2c653f5fea93531e9836abbd84342c1d1e17abc4a15084c2"}, + {file = "wrapt-1.15.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:96e25c8603a155559231c19c0349245eeb4ac0096fe3c1d0be5c47e075bd4f46"}, + {file = "wrapt-1.15.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:40737a081d7497efea35ab9304b829b857f21558acfc7b3272f908d33b0d9d4c"}, + {file = "wrapt-1.15.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:f87ec75864c37c4c6cb908d282e1969e79763e0d9becdfe9fe5473b7bb1e5f09"}, + {file = "wrapt-1.15.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:1286eb30261894e4c70d124d44b7fd07825340869945c79d05bda53a40caa079"}, + {file = "wrapt-1.15.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:493d389a2b63c88ad56cdc35d0fa5752daac56ca755805b1b0c530f785767d5e"}, + {file = "wrapt-1.15.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:58d7a75d731e8c63614222bcb21dd992b4ab01a399f1f09dd82af17bbfc2368a"}, + {file = "wrapt-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:21f6d9a0d5b3a207cdf7acf8e58d7d13d463e639f0c7e01d82cdb671e6cb7923"}, + {file = "wrapt-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ce42618f67741d4697684e501ef02f29e758a123aa2d669e2d964ff734ee00ee"}, + {file = "wrapt-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41d07d029dd4157ae27beab04d22b8e261eddfc6ecd64ff7000b10dc8b3a5727"}, + {file = "wrapt-1.15.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54accd4b8bc202966bafafd16e69da9d5640ff92389d33d28555c5fd4f25ccb7"}, + {file = "wrapt-1.15.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2fbfbca668dd15b744418265a9607baa970c347eefd0db6a518aaf0cfbd153c0"}, + {file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:76e9c727a874b4856d11a32fb0b389afc61ce8aaf281ada613713ddeadd1cfec"}, + {file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e20076a211cd6f9b44a6be58f7eeafa7ab5720eb796975d0c03f05b47d89eb90"}, + {file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a74d56552ddbde46c246b5b89199cb3fd182f9c346c784e1a93e4dc3f5ec9975"}, + {file = "wrapt-1.15.0-cp310-cp310-win32.whl", hash = "sha256:26458da5653aa5b3d8dc8b24192f574a58984c749401f98fff994d41d3f08da1"}, + {file = "wrapt-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:75760a47c06b5974aa5e01949bf7e66d2af4d08cb8c1d6516af5e39595397f5e"}, + {file = "wrapt-1.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ba1711cda2d30634a7e452fc79eabcadaffedf241ff206db2ee93dd2c89a60e7"}, + {file = "wrapt-1.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:56374914b132c702aa9aa9959c550004b8847148f95e1b824772d453ac204a72"}, + {file = "wrapt-1.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a89ce3fd220ff144bd9d54da333ec0de0399b52c9ac3d2ce34b569cf1a5748fb"}, + {file = "wrapt-1.15.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3bbe623731d03b186b3d6b0d6f51865bf598587c38d6f7b0be2e27414f7f214e"}, + {file = "wrapt-1.15.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3abbe948c3cbde2689370a262a8d04e32ec2dd4f27103669a45c6929bcdbfe7c"}, + {file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b67b819628e3b748fd3c2192c15fb951f549d0f47c0449af0764d7647302fda3"}, + {file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7eebcdbe3677e58dd4c0e03b4f2cfa346ed4049687d839adad68cc38bb559c92"}, + {file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:74934ebd71950e3db69960a7da29204f89624dde411afbfb3b4858c1409b1e98"}, + {file = "wrapt-1.15.0-cp311-cp311-win32.whl", hash = "sha256:bd84395aab8e4d36263cd1b9308cd504f6cf713b7d6d3ce25ea55670baec5416"}, + {file = "wrapt-1.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:a487f72a25904e2b4bbc0817ce7a8de94363bd7e79890510174da9d901c38705"}, + {file = "wrapt-1.15.0-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:4ff0d20f2e670800d3ed2b220d40984162089a6e2c9646fdb09b85e6f9a8fc29"}, + {file = "wrapt-1.15.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:9ed6aa0726b9b60911f4aed8ec5b8dd7bf3491476015819f56473ffaef8959bd"}, + {file = "wrapt-1.15.0-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:896689fddba4f23ef7c718279e42f8834041a21342d95e56922e1c10c0cc7afb"}, + {file = "wrapt-1.15.0-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:75669d77bb2c071333417617a235324a1618dba66f82a750362eccbe5b61d248"}, + {file = "wrapt-1.15.0-cp35-cp35m-win32.whl", hash = "sha256:fbec11614dba0424ca72f4e8ba3c420dba07b4a7c206c8c8e4e73f2e98f4c559"}, + {file = "wrapt-1.15.0-cp35-cp35m-win_amd64.whl", hash = "sha256:fd69666217b62fa5d7c6aa88e507493a34dec4fa20c5bd925e4bc12fce586639"}, + {file = "wrapt-1.15.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:b0724f05c396b0a4c36a3226c31648385deb6a65d8992644c12a4963c70326ba"}, + {file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bbeccb1aa40ab88cd29e6c7d8585582c99548f55f9b2581dfc5ba68c59a85752"}, + {file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:38adf7198f8f154502883242f9fe7333ab05a5b02de7d83aa2d88ea621f13364"}, + {file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:578383d740457fa790fdf85e6d346fda1416a40549fe8db08e5e9bd281c6a475"}, + {file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:a4cbb9ff5795cd66f0066bdf5947f170f5d63a9274f99bdbca02fd973adcf2a8"}, + {file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:af5bd9ccb188f6a5fdda9f1f09d9f4c86cc8a539bd48a0bfdc97723970348418"}, + {file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:b56d5519e470d3f2fe4aa7585f0632b060d532d0696c5bdfb5e8319e1d0f69a2"}, + {file = "wrapt-1.15.0-cp36-cp36m-win32.whl", hash = "sha256:77d4c1b881076c3ba173484dfa53d3582c1c8ff1f914c6461ab70c8428b796c1"}, + {file = "wrapt-1.15.0-cp36-cp36m-win_amd64.whl", hash = "sha256:077ff0d1f9d9e4ce6476c1a924a3332452c1406e59d90a2cf24aeb29eeac9420"}, + {file = "wrapt-1.15.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5c5aa28df055697d7c37d2099a7bc09f559d5053c3349b1ad0c39000e611d317"}, + {file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3a8564f283394634a7a7054b7983e47dbf39c07712d7b177b37e03f2467a024e"}, + {file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:780c82a41dc493b62fc5884fb1d3a3b81106642c5c5c78d6a0d4cbe96d62ba7e"}, + {file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e169e957c33576f47e21864cf3fc9ff47c223a4ebca8960079b8bd36cb014fd0"}, + {file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b02f21c1e2074943312d03d243ac4388319f2456576b2c6023041c4d57cd7019"}, + {file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f2e69b3ed24544b0d3dbe2c5c0ba5153ce50dcebb576fdc4696d52aa22db6034"}, + {file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d787272ed958a05b2c86311d3a4135d3c2aeea4fc655705f074130aa57d71653"}, + {file = "wrapt-1.15.0-cp37-cp37m-win32.whl", hash = "sha256:02fce1852f755f44f95af51f69d22e45080102e9d00258053b79367d07af39c0"}, + {file = "wrapt-1.15.0-cp37-cp37m-win_amd64.whl", hash = "sha256:abd52a09d03adf9c763d706df707c343293d5d106aea53483e0ec8d9e310ad5e"}, + {file = "wrapt-1.15.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cdb4f085756c96a3af04e6eca7f08b1345e94b53af8921b25c72f096e704e145"}, + {file = "wrapt-1.15.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:230ae493696a371f1dbffaad3dafbb742a4d27a0afd2b1aecebe52b740167e7f"}, + {file = "wrapt-1.15.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63424c681923b9f3bfbc5e3205aafe790904053d42ddcc08542181a30a7a51bd"}, + {file = "wrapt-1.15.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6bcbfc99f55655c3d93feb7ef3800bd5bbe963a755687cbf1f490a71fb7794b"}, + {file = "wrapt-1.15.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c99f4309f5145b93eca6e35ac1a988f0dc0a7ccf9ccdcd78d3c0adf57224e62f"}, + {file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b130fe77361d6771ecf5a219d8e0817d61b236b7d8b37cc045172e574ed219e6"}, + {file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:96177eb5645b1c6985f5c11d03fc2dbda9ad24ec0f3a46dcce91445747e15094"}, + {file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d5fe3e099cf07d0fb5a1e23d399e5d4d1ca3e6dfcbe5c8570ccff3e9208274f7"}, + {file = "wrapt-1.15.0-cp38-cp38-win32.whl", hash = "sha256:abd8f36c99512755b8456047b7be10372fca271bf1467a1caa88db991e7c421b"}, + {file = "wrapt-1.15.0-cp38-cp38-win_amd64.whl", hash = "sha256:b06fa97478a5f478fb05e1980980a7cdf2712015493b44d0c87606c1513ed5b1"}, + {file = "wrapt-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2e51de54d4fb8fb50d6ee8327f9828306a959ae394d3e01a1ba8b2f937747d86"}, + {file = "wrapt-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0970ddb69bba00670e58955f8019bec4a42d1785db3faa043c33d81de2bf843c"}, + {file = "wrapt-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76407ab327158c510f44ded207e2f76b657303e17cb7a572ffe2f5a8a48aa04d"}, + {file = "wrapt-1.15.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cd525e0e52a5ff16653a3fc9e3dd827981917d34996600bbc34c05d048ca35cc"}, + {file = "wrapt-1.15.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d37ac69edc5614b90516807de32d08cb8e7b12260a285ee330955604ed9dd29"}, + {file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:078e2a1a86544e644a68422f881c48b84fef6d18f8c7a957ffd3f2e0a74a0d4a"}, + {file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:2cf56d0e237280baed46f0b5316661da892565ff58309d4d2ed7dba763d984b8"}, + {file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7dc0713bf81287a00516ef43137273b23ee414fe41a3c14be10dd95ed98a2df9"}, + {file = "wrapt-1.15.0-cp39-cp39-win32.whl", hash = "sha256:46ed616d5fb42f98630ed70c3529541408166c22cdfd4540b88d5f21006b0eff"}, + {file = "wrapt-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:eef4d64c650f33347c1f9266fa5ae001440b232ad9b98f1f43dfe7a79435c0a6"}, + {file = "wrapt-1.15.0-py3-none-any.whl", hash = "sha256:64b1df0f83706b4ef4cfb4fb0e4c2669100fd7ecacfb59e091fad300d4e04640"}, + {file = "wrapt-1.15.0.tar.gz", hash = "sha256:d06730c6aed78cee4126234cf2d071e01b44b915e725a6cb439a879ec9754a3a"}, +] + +[metadata] +lock-version = "2.0" +python-versions = "^3.10" +content-hash = "18eb76a106ed41effeddd4dcd8acf90b85b09d7a9e31dd965cb9462c2c7166a9" diff --git a/scripts/integrations-cli/pyproject.toml b/scripts/integrations-cli/pyproject.toml index ccc567ff6..ace8da909 100644 --- a/scripts/integrations-cli/pyproject.toml +++ b/scripts/integrations-cli/pyproject.toml @@ -9,7 +9,7 @@ license = "Apache-2.0" profile = "black" [tool.pylint] -disable = "missing-function-docstring" +disable = "C,R" [tool.poetry.dependencies] python = "^3.10" @@ -21,6 +21,7 @@ jsonschema = "^4.17.3" [tool.poetry.dev-dependencies] black = "^23.3.0" isort = "^5.12.0" +pylint = "^2.17.1" [build-system] requires = ["poetry-core>=1.0.0"] diff --git a/scripts/integrations-cli/tests/test_validate.py b/scripts/integrations-cli/tests/test_validate.py index 3d8390202..195492da2 100644 --- a/scripts/integrations-cli/tests/test_validate.py +++ b/scripts/integrations-cli/tests/test_validate.py @@ -15,8 +15,6 @@ def test_config_schema_is_valid(self): class TestConfigValidations(unittest.TestCase): - """Test validations pertaining to config objects""" - def test_default_config_is_valid(self): config = deepcopy(constants.DEFAULT_CONFIG) assert is_successful(validate.validate_config(config)) From d0cf5c19d0c5739834f343348b30c279e068d7b9 Mon Sep 17 00:00:00 2001 From: Simeon Widdis Date: Fri, 31 Mar 2023 16:43:28 -0700 Subject: [PATCH 08/40] Add catalog selection support Signed-off-by: Simeon Widdis --- scripts/integrations-cli/helpers/__init__.py | 1 + scripts/integrations-cli/helpers/catalog.py | 22 +++++++++++++++++++ scripts/integrations-cli/helpers/constants.py | 10 ++++----- scripts/integrations-cli/helpers/create.py | 17 ++++++++++---- scripts/integrations-cli/helpers/validate.py | 9 +++++++- scripts/integrations-cli/integrations-cli.py | 12 ++++++++-- .../integrations-cli/tests/test_validate.py | 8 ++++++- 7 files changed, 65 insertions(+), 14 deletions(-) create mode 100644 scripts/integrations-cli/helpers/catalog.py diff --git a/scripts/integrations-cli/helpers/__init__.py b/scripts/integrations-cli/helpers/__init__.py index 05afb1b7e..56c892129 100644 --- a/scripts/integrations-cli/helpers/__init__.py +++ b/scripts/integrations-cli/helpers/__init__.py @@ -1,2 +1,3 @@ from . import constants, validate +from .catalog import CatalogManager from .create import IntegrationBuilder diff --git a/scripts/integrations-cli/helpers/catalog.py b/scripts/integrations-cli/helpers/catalog.py new file mode 100644 index 000000000..7b365228a --- /dev/null +++ b/scripts/integrations-cli/helpers/catalog.py @@ -0,0 +1,22 @@ +import json +import os +from functools import cache + +from returns.io import impure_safe + +from . import constants, validate + + +@impure_safe +def _load_catalog_file() -> dict: + catalog_path = os.path.join(constants.SCHEMA_ROOT, "observability/catalog.json") + with open(catalog_path, "r", encoding="utf-8") as catalog_file: + return json.load(catalog_file) + + +class CatalogManager: + @cache + def __init__(self): + catalog = _load_catalog_file().bind_result(validate.validate_catalog) + # For now just re-throw exceptions on catalog load failure + self.catalog = catalog.unwrap()._inner_value diff --git a/scripts/integrations-cli/helpers/constants.py b/scripts/integrations-cli/helpers/constants.py index 90d56393c..a6c7ccfa5 100644 --- a/scripts/integrations-cli/helpers/constants.py +++ b/scripts/integrations-cli/helpers/constants.py @@ -2,7 +2,7 @@ import json import os -_SCHEMA_ROOT = "../../src/main/resources/schema" +SCHEMA_ROOT = "../../src/main/resources/schema" DEFAULT_CONFIG = { "template-name": "default", @@ -18,10 +18,8 @@ SCHEMAS = {} # For now, assume we're running in the current relative directory -if os.path.isdir(_SCHEMA_ROOT): - for filename in glob.glob( - os.path.join(_SCHEMA_ROOT, "**/*.schema"), recursive=True - ): +if os.path.isdir(SCHEMA_ROOT): + for filename in glob.glob(os.path.join(SCHEMA_ROOT, "**/*.schema"), recursive=True): schema_name = os.path.split(filename)[1] - with open(filename, "r") as schema_file: + with open(filename, "r", encoding="utf-8") as schema_file: SCHEMAS[schema_name] = json.load(schema_file) diff --git a/scripts/integrations-cli/helpers/create.py b/scripts/integrations-cli/helpers/create.py index f4e6e9d2e..159ac50eb 100644 --- a/scripts/integrations-cli/helpers/create.py +++ b/scripts/integrations-cli/helpers/create.py @@ -1,11 +1,11 @@ import json import os -from urllib import parse +import re from copy import deepcopy +from urllib import parse from .constants import DEFAULT_CONFIG from .validate import validate_config -import re class IntegrationBuilder: @@ -26,27 +26,36 @@ def with_schema_version(self, version: str) -> "IntegrationBuilder": if not re.match(r"^\d+\.\d+\.\d+", version): raise ValueError("Invalid version") self.config["version"]["schema"] = version + return self def with_resource_version(self, version: str) -> "IntegrationBuilder": if not re.match(r"^\^?\d+\.\d+\.\d+", version): raise ValueError("Invalid version") self.config["version"]["resource"] = version + return self def with_description(self, desc: str) -> "IntegrationBuilder": self.config["description"] = desc + return self def with_catalog(self, catalog: str) -> "IntegrationBuilder": self.config["catalog"] = catalog + return self def with_repository(self, repo_url: str) -> "IntegrationBuilder": - if not parse.urlparse(repo_url): + if not parse.urlparse(repo_url, allow_fragments=False): raise ValueError("Invalid URL") self.config["repository"]["url"] = repo_url + return self + + def with_component(self, component: dict) -> "IntegrationBuilder": + self.config["components"].append(component) + return self def build(self): assert self.path is not None os.makedirs(self.path, exist_ok=True) - files = {"config.json": validate_config(self.config)} + files = {"config.json": validate_config(self.config).unwrap()} for filename, data in files.items(): with open(os.path.join(self.path, filename), "w") as file: json.dump(data, file, ensure_ascii=False, indent=2) diff --git a/scripts/integrations-cli/helpers/validate.py b/scripts/integrations-cli/helpers/validate.py index 50d2166a3..ee8b085b0 100644 --- a/scripts/integrations-cli/helpers/validate.py +++ b/scripts/integrations-cli/helpers/validate.py @@ -1,5 +1,5 @@ -from returns.result import Result, Failure, safe import jsonschema +from returns.result import Failure, Result, safe from .constants import SCHEMAS @@ -20,3 +20,10 @@ def validate_config(config: dict) -> Result[dict, Exception]: return validate_instance(config, SCHEMAS["integration.schema"]) except KeyError as err: return Failure(err) + + +def validate_catalog(catalog: dict) -> Result[dict, Exception]: + try: + return validate_instance(catalog, SCHEMAS["catalog.schema"]) + except KeyError as err: + return Failure(err) diff --git a/scripts/integrations-cli/integrations-cli.py b/scripts/integrations-cli/integrations-cli.py index 00a44df9f..a7e6f3fd4 100644 --- a/scripts/integrations-cli/integrations-cli.py +++ b/scripts/integrations-cli/integrations-cli.py @@ -15,9 +15,17 @@ def integrations_cli(): """Create and maintain Integrations for the OpenSearch Integrations Plugin.""" -def do_add_component(_builder: helpers.IntegrationBuilder) -> bool: +def do_add_component(builder: helpers.IntegrationBuilder) -> bool: """Start an interactive session for""" - click.echo("Interactive component definition is work-in-progress. Sorry!") + manager = helpers.CatalogManager() + choices = {} + for category in manager.catalog["categories"]: + click.echo(f"- Category {category['category']}") + for component in category["components"]: + click.echo(f" - {component['component']}: {component['description']}") + choices[component["component"]] = component + component = click.prompt("Select component", type=click.Choice(list(choices)), show_choices=False) + builder.with_component(component) return ( click.prompt( "Configure another component? (y/n)", diff --git a/scripts/integrations-cli/tests/test_validate.py b/scripts/integrations-cli/tests/test_validate.py index 195492da2..7def2291b 100644 --- a/scripts/integrations-cli/tests/test_validate.py +++ b/scripts/integrations-cli/tests/test_validate.py @@ -2,10 +2,11 @@ from copy import deepcopy import jsonschema +from returns.pipeline import is_successful import helpers.constants as constants import helpers.validate as validate -from returns.pipeline import is_successful +from helpers.catalog import _load_catalog_file class TestSchemas(unittest.TestCase): @@ -28,3 +29,8 @@ def test_default_with_integer_description_is_invalid(self): config = deepcopy(constants.DEFAULT_CONFIG) config["description"] = 0 assert not is_successful(validate.validate_config(config)) + +class TestCatalogValidations(unittest.TestCase): + def test_catalog_is_valid(self): + catalog = _load_catalog_file().bind_result(validate.validate_catalog) + return is_successful(catalog) From 5d861730ff70bb8178d5b7fb8a60a56c928c0b04 Mon Sep 17 00:00:00 2001 From: Simeon Widdis Date: Fri, 31 Mar 2023 16:44:53 -0700 Subject: [PATCH 09/40] Tweak catalog schema to pass validation for catalog Signed-off-by: Simeon Widdis --- src/main/resources/schema/system/catalog.schema | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/resources/schema/system/catalog.schema b/src/main/resources/schema/system/catalog.schema index 2c8a8c7f9..c7a3e7357 100644 --- a/src/main/resources/schema/system/catalog.schema +++ b/src/main/resources/schema/system/catalog.schema @@ -4,7 +4,7 @@ "definitions": { "Catalog": { "type": "object", - "additionalProperties": false, + "additionalProperties": true, "properties": { "catalog": { "type": "string" @@ -36,7 +36,7 @@ }, "Category": { "type": "object", - "additionalProperties": false, + "additionalProperties": true, "properties": { "category": { "type": "string" @@ -68,7 +68,7 @@ }, "Component": { "type": "object", - "additionalProperties": false, + "additionalProperties": true, "properties": { "component": { "type": "string" From 9265e58b0714e6a242b8b7a0db4fd469fb5a1719 Mon Sep 17 00:00:00 2001 From: Simeon Widdis Date: Mon, 3 Apr 2023 10:55:28 -0700 Subject: [PATCH 10/40] Refactor validation logic Signed-off-by: Simeon Widdis --- scripts/integrations-cli/helpers/create.py | 2 +- scripts/integrations-cli/integrations-cli.py | 25 ++++++++++++-------- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/scripts/integrations-cli/helpers/create.py b/scripts/integrations-cli/helpers/create.py index 159ac50eb..30e263396 100644 --- a/scripts/integrations-cli/helpers/create.py +++ b/scripts/integrations-cli/helpers/create.py @@ -57,5 +57,5 @@ def build(self): os.makedirs(self.path, exist_ok=True) files = {"config.json": validate_config(self.config).unwrap()} for filename, data in files.items(): - with open(os.path.join(self.path, filename), "w") as file: + with open(os.path.join(self.path, filename), "w", encoding="utf-8") as file: json.dump(data, file, ensure_ascii=False, indent=2) diff --git a/scripts/integrations-cli/integrations-cli.py b/scripts/integrations-cli/integrations-cli.py index a7e6f3fd4..56a928dd1 100644 --- a/scripts/integrations-cli/integrations-cli.py +++ b/scripts/integrations-cli/integrations-cli.py @@ -4,8 +4,9 @@ import zipfile import click -import jsonschema from termcolor import colored +from returns.pipeline import is_successful +from returns.result import Result import helpers @@ -76,21 +77,25 @@ def create(name: str): click.echo(colored(f"Integration created at '{integration_path}'", "green")) +def validate_component(path: str, validator) -> Result[dict, Exception]: + with open(path, "r", encoding="utf-8") as item_data: + loaded = json.load(item_data) + result = validator(loaded) + if not is_successful(result): + msg = str(result.failure) + msg = ("> " + msg).replace("\n", "\n> ") + click.echo(colored(msg, "red"), err=True) + return result + + def full_integration_is_valid(name: str) -> bool: integration_path = os.path.join(os.getcwd(), "integrations", name) integration_parts = {"config.json": helpers.validate.validate_config} encountered_errors = False for item, validator in integration_parts.items(): item_path = os.path.join(integration_path, item) - with open(item_path, "r") as item_data: - try: - loaded = json.load(item_data) - validator(loaded) - except jsonschema.exceptions.ValidationError as err: - click.echo(colored(f"'{item_path}' is invalid", "red")) - err_msg = ("> " + str(err)).replace("\n", "\n> ") - click.echo(colored(err_msg, "red"), err=True) - encountered_errors = True + if not is_successful(validate_component(item_path, validator)): + encountered_errors = True return not encountered_errors From 15f7a13c1fe6245061e93807bab21a2368dd1f5b Mon Sep 17 00:00:00 2001 From: Simeon Widdis Date: Mon, 3 Apr 2023 11:01:23 -0700 Subject: [PATCH 11/40] Reformat Signed-off-by: Simeon Widdis --- scripts/integrations-cli/helpers/create.py | 2 +- scripts/integrations-cli/integrations-cli.py | 6 ++++-- scripts/integrations-cli/tests/test_validate.py | 1 + 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/scripts/integrations-cli/helpers/create.py b/scripts/integrations-cli/helpers/create.py index 30e263396..233d9eeb7 100644 --- a/scripts/integrations-cli/helpers/create.py +++ b/scripts/integrations-cli/helpers/create.py @@ -47,7 +47,7 @@ def with_repository(self, repo_url: str) -> "IntegrationBuilder": raise ValueError("Invalid URL") self.config["repository"]["url"] = repo_url return self - + def with_component(self, component: dict) -> "IntegrationBuilder": self.config["components"].append(component) return self diff --git a/scripts/integrations-cli/integrations-cli.py b/scripts/integrations-cli/integrations-cli.py index 56a928dd1..aea7f8f3a 100644 --- a/scripts/integrations-cli/integrations-cli.py +++ b/scripts/integrations-cli/integrations-cli.py @@ -4,9 +4,9 @@ import zipfile import click -from termcolor import colored from returns.pipeline import is_successful from returns.result import Result +from termcolor import colored import helpers @@ -25,7 +25,9 @@ def do_add_component(builder: helpers.IntegrationBuilder) -> bool: for component in category["components"]: click.echo(f" - {component['component']}: {component['description']}") choices[component["component"]] = component - component = click.prompt("Select component", type=click.Choice(list(choices)), show_choices=False) + component = click.prompt( + "Select component", type=click.Choice(list(choices)), show_choices=False + ) builder.with_component(component) return ( click.prompt( diff --git a/scripts/integrations-cli/tests/test_validate.py b/scripts/integrations-cli/tests/test_validate.py index 7def2291b..de2e7bb6d 100644 --- a/scripts/integrations-cli/tests/test_validate.py +++ b/scripts/integrations-cli/tests/test_validate.py @@ -30,6 +30,7 @@ def test_default_with_integer_description_is_invalid(self): config["description"] = 0 assert not is_successful(validate.validate_config(config)) + class TestCatalogValidations(unittest.TestCase): def test_catalog_is_valid(self): catalog = _load_catalog_file().bind_result(validate.validate_catalog) From d5d1dd1fb43a9ce2394d46489f6c04c9d16f17a4 Mon Sep 17 00:00:00 2001 From: Simeon Widdis Date: Mon, 3 Apr 2023 11:01:40 -0700 Subject: [PATCH 12/40] Add poetry to CI Signed-off-by: Simeon Widdis --- .github/workflows/python-poetry.yml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 .github/workflows/python-poetry.yml diff --git a/.github/workflows/python-poetry.yml b/.github/workflows/python-poetry.yml new file mode 100644 index 000000000..6f46b890f --- /dev/null +++ b/.github/workflows/python-poetry.yml @@ -0,0 +1,23 @@ +name: Python Poetry CI +on: pull_request + +jobs: + ci: + strategy: + fail-fast: false + matrix: + python-version: ["3.10"] + poetry-version: ["1.0"] + os: [ubuntu-18.04, macos-latest, windows-latest] + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + - name: Run image + uses: abatilo/actions-poetry@v2 + with: + poetry-version: ${{ matrix.poetry-version }} + - name: Run Integrations CLI unit tests + run: cd scripts/integrations-cli && poetry run python -m unittest \ No newline at end of file From 99c72e90410f90e87f50800378d1593f6dcce7a6 Mon Sep 17 00:00:00 2001 From: Simeon Widdis Date: Mon, 3 Apr 2023 11:21:17 -0700 Subject: [PATCH 13/40] Refresh poetry lock Signed-off-by: Simeon Widdis --- scripts/integrations-cli/poetry.lock | 782 ++++++++++----------------- 1 file changed, 281 insertions(+), 501 deletions(-) diff --git a/scripts/integrations-cli/poetry.lock b/scripts/integrations-cli/poetry.lock index 4e45c5102..e324e602a 100644 --- a/scripts/integrations-cli/poetry.lock +++ b/scripts/integrations-cli/poetry.lock @@ -1,501 +1,281 @@ -# This file is automatically @generated by Poetry 1.4.1 and should not be changed by hand. - -[[package]] -name = "astroid" -version = "2.15.1" -description = "An abstract syntax tree for Python with inference support." -category = "dev" -optional = false -python-versions = ">=3.7.2" -files = [ - {file = "astroid-2.15.1-py3-none-any.whl", hash = "sha256:89860bda98fe2bbd1f5d262229be7629d778ce280de68d95d4a73d1f592ad268"}, - {file = "astroid-2.15.1.tar.gz", hash = "sha256:af4e0aff46e2868218502789898269ed95b663fba49e65d91c1e09c966266c34"}, -] - -[package.dependencies] -lazy-object-proxy = ">=1.4.0" -typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.11\""} -wrapt = [ - {version = ">=1.11,<2", markers = "python_version < \"3.11\""}, - {version = ">=1.14,<2", markers = "python_version >= \"3.11\""}, -] - -[[package]] -name = "attrs" -version = "22.2.0" -description = "Classes Without Boilerplate" -category = "main" -optional = false -python-versions = ">=3.6" -files = [ - {file = "attrs-22.2.0-py3-none-any.whl", hash = "sha256:29e95c7f6778868dbd49170f98f8818f78f3dc5e0e37c0b1f474e3561b240836"}, - {file = "attrs-22.2.0.tar.gz", hash = "sha256:c9227bfc2f01993c03f68db37d1d15c9690188323c067c641f1a35ca58185f99"}, -] - -[package.extras] -cov = ["attrs[tests]", "coverage-enable-subprocess", "coverage[toml] (>=5.3)"] -dev = ["attrs[docs,tests]"] -docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope.interface"] -tests = ["attrs[tests-no-zope]", "zope.interface"] -tests-no-zope = ["cloudpickle", "cloudpickle", "hypothesis", "hypothesis", "mypy (>=0.971,<0.990)", "mypy (>=0.971,<0.990)", "pympler", "pympler", "pytest (>=4.3.0)", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-mypy-plugins", "pytest-xdist[psutil]", "pytest-xdist[psutil]"] - -[[package]] -name = "black" -version = "23.3.0" -description = "The uncompromising code formatter." -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "black-23.3.0-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:0945e13506be58bf7db93ee5853243eb368ace1c08a24c65ce108986eac65915"}, - {file = "black-23.3.0-cp310-cp310-macosx_10_16_universal2.whl", hash = "sha256:67de8d0c209eb5b330cce2469503de11bca4085880d62f1628bd9972cc3366b9"}, - {file = "black-23.3.0-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:7c3eb7cea23904399866c55826b31c1f55bbcd3890ce22ff70466b907b6775c2"}, - {file = "black-23.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:32daa9783106c28815d05b724238e30718f34155653d4d6e125dc7daec8e260c"}, - {file = "black-23.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:35d1381d7a22cc5b2be2f72c7dfdae4072a3336060635718cc7e1ede24221d6c"}, - {file = "black-23.3.0-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:a8a968125d0a6a404842fa1bf0b349a568634f856aa08ffaff40ae0dfa52e7c6"}, - {file = "black-23.3.0-cp311-cp311-macosx_10_16_universal2.whl", hash = "sha256:c7ab5790333c448903c4b721b59c0d80b11fe5e9803d8703e84dcb8da56fec1b"}, - {file = "black-23.3.0-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:a6f6886c9869d4daae2d1715ce34a19bbc4b95006d20ed785ca00fa03cba312d"}, - {file = "black-23.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f3c333ea1dd6771b2d3777482429864f8e258899f6ff05826c3a4fcc5ce3f70"}, - {file = "black-23.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:11c410f71b876f961d1de77b9699ad19f939094c3a677323f43d7a29855fe326"}, - {file = "black-23.3.0-cp37-cp37m-macosx_10_16_x86_64.whl", hash = "sha256:1d06691f1eb8de91cd1b322f21e3bfc9efe0c7ca1f0e1eb1db44ea367dff656b"}, - {file = "black-23.3.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50cb33cac881766a5cd9913e10ff75b1e8eb71babf4c7104f2e9c52da1fb7de2"}, - {file = "black-23.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:e114420bf26b90d4b9daa597351337762b63039752bdf72bf361364c1aa05925"}, - {file = "black-23.3.0-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:48f9d345675bb7fbc3dd85821b12487e1b9a75242028adad0333ce36ed2a6d27"}, - {file = "black-23.3.0-cp38-cp38-macosx_10_16_universal2.whl", hash = "sha256:714290490c18fb0126baa0fca0a54ee795f7502b44177e1ce7624ba1c00f2331"}, - {file = "black-23.3.0-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:064101748afa12ad2291c2b91c960be28b817c0c7eaa35bec09cc63aa56493c5"}, - {file = "black-23.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:562bd3a70495facf56814293149e51aa1be9931567474993c7942ff7d3533961"}, - {file = "black-23.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:e198cf27888ad6f4ff331ca1c48ffc038848ea9f031a3b40ba36aced7e22f2c8"}, - {file = "black-23.3.0-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:3238f2aacf827d18d26db07524e44741233ae09a584273aa059066d644ca7b30"}, - {file = "black-23.3.0-cp39-cp39-macosx_10_16_universal2.whl", hash = "sha256:f0bd2f4a58d6666500542b26354978218a9babcdc972722f4bf90779524515f3"}, - {file = "black-23.3.0-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:92c543f6854c28a3c7f39f4d9b7694f9a6eb9d3c5e2ece488c327b6e7ea9b266"}, - {file = "black-23.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a150542a204124ed00683f0db1f5cf1c2aaaa9cc3495b7a3b5976fb136090ab"}, - {file = "black-23.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:6b39abdfb402002b8a7d030ccc85cf5afff64ee90fa4c5aebc531e3ad0175ddb"}, - {file = "black-23.3.0-py3-none-any.whl", hash = "sha256:ec751418022185b0c1bb7d7736e6933d40bbb14c14a0abcf9123d1b159f98dd4"}, - {file = "black-23.3.0.tar.gz", hash = "sha256:1c7b8d606e728a41ea1ccbd7264677e494e87cf630e399262ced92d4a8dac940"}, -] - -[package.dependencies] -click = ">=8.0.0" -mypy-extensions = ">=0.4.3" -packaging = ">=22.0" -pathspec = ">=0.9.0" -platformdirs = ">=2" -tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} - -[package.extras] -colorama = ["colorama (>=0.4.3)"] -d = ["aiohttp (>=3.7.4)"] -jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] -uvloop = ["uvloop (>=0.15.2)"] - -[[package]] -name = "click" -version = "8.1.3" -description = "Composable command line interface toolkit" -category = "main" -optional = false -python-versions = ">=3.7" -files = [ - {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"}, - {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "platform_system == \"Windows\""} - -[[package]] -name = "colorama" -version = "0.4.6" -description = "Cross-platform colored terminal text." -category = "main" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" -files = [ - {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, - {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, -] - -[[package]] -name = "dill" -version = "0.3.6" -description = "serialize all of python" -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "dill-0.3.6-py3-none-any.whl", hash = "sha256:a07ffd2351b8c678dfc4a856a3005f8067aea51d6ba6c700796a4d9e280f39f0"}, - {file = "dill-0.3.6.tar.gz", hash = "sha256:e5db55f3687856d8fbdab002ed78544e1c4559a130302693d839dfe8f93f2373"}, -] - -[package.extras] -graph = ["objgraph (>=1.7.2)"] - -[[package]] -name = "isort" -version = "5.12.0" -description = "A Python utility / library to sort Python imports." -category = "dev" -optional = false -python-versions = ">=3.8.0" -files = [ - {file = "isort-5.12.0-py3-none-any.whl", hash = "sha256:f84c2818376e66cf843d497486ea8fed8700b340f308f076c6fb1229dff318b6"}, - {file = "isort-5.12.0.tar.gz", hash = "sha256:8bef7dde241278824a6d83f44a544709b065191b95b6e50894bdc722fcba0504"}, -] - -[package.extras] -colors = ["colorama (>=0.4.3)"] -pipfile-deprecated-finder = ["pip-shims (>=0.5.2)", "pipreqs", "requirementslib"] -plugins = ["setuptools"] -requirements-deprecated-finder = ["pip-api", "pipreqs"] - -[[package]] -name = "jsonschema" -version = "4.17.3" -description = "An implementation of JSON Schema validation for Python" -category = "main" -optional = false -python-versions = ">=3.7" -files = [ - {file = "jsonschema-4.17.3-py3-none-any.whl", hash = "sha256:a870ad254da1a8ca84b6a2905cac29d265f805acc57af304784962a2aa6508f6"}, - {file = "jsonschema-4.17.3.tar.gz", hash = "sha256:0f864437ab8b6076ba6707453ef8f98a6a0d512a80e93f8abdb676f737ecb60d"}, -] - -[package.dependencies] -attrs = ">=17.4.0" -pyrsistent = ">=0.14.0,<0.17.0 || >0.17.0,<0.17.1 || >0.17.1,<0.17.2 || >0.17.2" - -[package.extras] -format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"] -format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "uri-template", "webcolors (>=1.11)"] - -[[package]] -name = "lazy-object-proxy" -version = "1.9.0" -description = "A fast and thorough lazy object proxy." -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "lazy-object-proxy-1.9.0.tar.gz", hash = "sha256:659fb5809fa4629b8a1ac5106f669cfc7bef26fbb389dda53b3e010d1ac4ebae"}, - {file = "lazy_object_proxy-1.9.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b40387277b0ed2d0602b8293b94d7257e17d1479e257b4de114ea11a8cb7f2d7"}, - {file = "lazy_object_proxy-1.9.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8c6cfb338b133fbdbc5cfaa10fe3c6aeea827db80c978dbd13bc9dd8526b7d4"}, - {file = "lazy_object_proxy-1.9.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:721532711daa7db0d8b779b0bb0318fa87af1c10d7fe5e52ef30f8eff254d0cd"}, - {file = "lazy_object_proxy-1.9.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:66a3de4a3ec06cd8af3f61b8e1ec67614fbb7c995d02fa224813cb7afefee701"}, - {file = "lazy_object_proxy-1.9.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:1aa3de4088c89a1b69f8ec0dcc169aa725b0ff017899ac568fe44ddc1396df46"}, - {file = "lazy_object_proxy-1.9.0-cp310-cp310-win32.whl", hash = "sha256:f0705c376533ed2a9e5e97aacdbfe04cecd71e0aa84c7c0595d02ef93b6e4455"}, - {file = "lazy_object_proxy-1.9.0-cp310-cp310-win_amd64.whl", hash = "sha256:ea806fd4c37bf7e7ad82537b0757999264d5f70c45468447bb2b91afdbe73a6e"}, - {file = "lazy_object_proxy-1.9.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:946d27deaff6cf8452ed0dba83ba38839a87f4f7a9732e8f9fd4107b21e6ff07"}, - {file = "lazy_object_proxy-1.9.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79a31b086e7e68b24b99b23d57723ef7e2c6d81ed21007b6281ebcd1688acb0a"}, - {file = "lazy_object_proxy-1.9.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f699ac1c768270c9e384e4cbd268d6e67aebcfae6cd623b4d7c3bfde5a35db59"}, - {file = "lazy_object_proxy-1.9.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bfb38f9ffb53b942f2b5954e0f610f1e721ccebe9cce9025a38c8ccf4a5183a4"}, - {file = "lazy_object_proxy-1.9.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:189bbd5d41ae7a498397287c408617fe5c48633e7755287b21d741f7db2706a9"}, - {file = "lazy_object_proxy-1.9.0-cp311-cp311-win32.whl", hash = "sha256:81fc4d08b062b535d95c9ea70dbe8a335c45c04029878e62d744bdced5141586"}, - {file = "lazy_object_proxy-1.9.0-cp311-cp311-win_amd64.whl", hash = "sha256:f2457189d8257dd41ae9b434ba33298aec198e30adf2dcdaaa3a28b9994f6adb"}, - {file = "lazy_object_proxy-1.9.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:d9e25ef10a39e8afe59a5c348a4dbf29b4868ab76269f81ce1674494e2565a6e"}, - {file = "lazy_object_proxy-1.9.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cbf9b082426036e19c6924a9ce90c740a9861e2bdc27a4834fd0a910742ac1e8"}, - {file = "lazy_object_proxy-1.9.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f5fa4a61ce2438267163891961cfd5e32ec97a2c444e5b842d574251ade27d2"}, - {file = "lazy_object_proxy-1.9.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:8fa02eaab317b1e9e03f69aab1f91e120e7899b392c4fc19807a8278a07a97e8"}, - {file = "lazy_object_proxy-1.9.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e7c21c95cae3c05c14aafffe2865bbd5e377cfc1348c4f7751d9dc9a48ca4bda"}, - {file = "lazy_object_proxy-1.9.0-cp37-cp37m-win32.whl", hash = "sha256:f12ad7126ae0c98d601a7ee504c1122bcef553d1d5e0c3bfa77b16b3968d2734"}, - {file = "lazy_object_proxy-1.9.0-cp37-cp37m-win_amd64.whl", hash = "sha256:edd20c5a55acb67c7ed471fa2b5fb66cb17f61430b7a6b9c3b4a1e40293b1671"}, - {file = "lazy_object_proxy-1.9.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2d0daa332786cf3bb49e10dc6a17a52f6a8f9601b4cf5c295a4f85854d61de63"}, - {file = "lazy_object_proxy-1.9.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cd077f3d04a58e83d04b20e334f678c2b0ff9879b9375ed107d5d07ff160171"}, - {file = "lazy_object_proxy-1.9.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:660c94ea760b3ce47d1855a30984c78327500493d396eac4dfd8bd82041b22be"}, - {file = "lazy_object_proxy-1.9.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:212774e4dfa851e74d393a2370871e174d7ff0ebc980907723bb67d25c8a7c30"}, - {file = "lazy_object_proxy-1.9.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:f0117049dd1d5635bbff65444496c90e0baa48ea405125c088e93d9cf4525b11"}, - {file = "lazy_object_proxy-1.9.0-cp38-cp38-win32.whl", hash = "sha256:0a891e4e41b54fd5b8313b96399f8b0e173bbbfc03c7631f01efbe29bb0bcf82"}, - {file = "lazy_object_proxy-1.9.0-cp38-cp38-win_amd64.whl", hash = "sha256:9990d8e71b9f6488e91ad25f322898c136b008d87bf852ff65391b004da5e17b"}, - {file = "lazy_object_proxy-1.9.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9e7551208b2aded9c1447453ee366f1c4070602b3d932ace044715d89666899b"}, - {file = "lazy_object_proxy-1.9.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f83ac4d83ef0ab017683d715ed356e30dd48a93746309c8f3517e1287523ef4"}, - {file = "lazy_object_proxy-1.9.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7322c3d6f1766d4ef1e51a465f47955f1e8123caee67dd641e67d539a534d006"}, - {file = "lazy_object_proxy-1.9.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:18b78ec83edbbeb69efdc0e9c1cb41a3b1b1ed11ddd8ded602464c3fc6020494"}, - {file = "lazy_object_proxy-1.9.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:09763491ce220c0299688940f8dc2c5d05fd1f45af1e42e636b2e8b2303e4382"}, - {file = "lazy_object_proxy-1.9.0-cp39-cp39-win32.whl", hash = "sha256:9090d8e53235aa280fc9239a86ae3ea8ac58eff66a705fa6aa2ec4968b95c821"}, - {file = "lazy_object_proxy-1.9.0-cp39-cp39-win_amd64.whl", hash = "sha256:db1c1722726f47e10e0b5fdbf15ac3b8adb58c091d12b3ab713965795036985f"}, -] - -[[package]] -name = "mccabe" -version = "0.7.0" -description = "McCabe checker, plugin for flake8" -category = "dev" -optional = false -python-versions = ">=3.6" -files = [ - {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, - {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, -] - -[[package]] -name = "mypy-extensions" -version = "1.0.0" -description = "Type system extensions for programs checked with the mypy type checker." -category = "dev" -optional = false -python-versions = ">=3.5" -files = [ - {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, - {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, -] - -[[package]] -name = "packaging" -version = "23.0" -description = "Core utilities for Python packages" -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "packaging-23.0-py3-none-any.whl", hash = "sha256:714ac14496c3e68c99c29b00845f7a2b85f3bb6f1078fd9f72fd20f0570002b2"}, - {file = "packaging-23.0.tar.gz", hash = "sha256:b6ad297f8907de0fa2fe1ccbd26fdaf387f5f47c7275fedf8cce89f99446cf97"}, -] - -[[package]] -name = "pathspec" -version = "0.11.1" -description = "Utility library for gitignore style pattern matching of file paths." -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "pathspec-0.11.1-py3-none-any.whl", hash = "sha256:d8af70af76652554bd134c22b3e8a1cc46ed7d91edcdd721ef1a0c51a84a5293"}, - {file = "pathspec-0.11.1.tar.gz", hash = "sha256:2798de800fa92780e33acca925945e9a19a133b715067cf165b8866c15a31687"}, -] - -[[package]] -name = "platformdirs" -version = "3.2.0" -description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "platformdirs-3.2.0-py3-none-any.whl", hash = "sha256:ebe11c0d7a805086e99506aa331612429a72ca7cd52a1f0d277dc4adc20cb10e"}, - {file = "platformdirs-3.2.0.tar.gz", hash = "sha256:d5b638ca397f25f979350ff789db335903d7ea010ab28903f57b27e1b16c2b08"}, -] - -[package.extras] -docs = ["furo (>=2022.12.7)", "proselint (>=0.13)", "sphinx (>=6.1.3)", "sphinx-autodoc-typehints (>=1.22,!=1.23.4)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.2.2)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"] - -[[package]] -name = "pylint" -version = "2.17.1" -description = "python code static checker" -category = "dev" -optional = false -python-versions = ">=3.7.2" -files = [ - {file = "pylint-2.17.1-py3-none-any.whl", hash = "sha256:8660a54e3f696243d644fca98f79013a959c03f979992c1ab59c24d3f4ec2700"}, - {file = "pylint-2.17.1.tar.gz", hash = "sha256:d4d009b0116e16845533bc2163493d6681846ac725eab8ca8014afb520178ddd"}, -] - -[package.dependencies] -astroid = ">=2.15.0,<=2.17.0-dev0" -colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} -dill = [ - {version = ">=0.2", markers = "python_version < \"3.11\""}, - {version = ">=0.3.6", markers = "python_version >= \"3.11\""}, -] -isort = ">=4.2.5,<6" -mccabe = ">=0.6,<0.8" -platformdirs = ">=2.2.0" -tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} -tomlkit = ">=0.10.1" - -[package.extras] -spelling = ["pyenchant (>=3.2,<4.0)"] -testutils = ["gitpython (>3)"] - -[[package]] -name = "pyrsistent" -version = "0.19.3" -description = "Persistent/Functional/Immutable data structures" -category = "main" -optional = false -python-versions = ">=3.7" -files = [ - {file = "pyrsistent-0.19.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:20460ac0ea439a3e79caa1dbd560344b64ed75e85d8703943e0b66c2a6150e4a"}, - {file = "pyrsistent-0.19.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4c18264cb84b5e68e7085a43723f9e4c1fd1d935ab240ce02c0324a8e01ccb64"}, - {file = "pyrsistent-0.19.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4b774f9288dda8d425adb6544e5903f1fb6c273ab3128a355c6b972b7df39dcf"}, - {file = "pyrsistent-0.19.3-cp310-cp310-win32.whl", hash = "sha256:5a474fb80f5e0d6c9394d8db0fc19e90fa540b82ee52dba7d246a7791712f74a"}, - {file = "pyrsistent-0.19.3-cp310-cp310-win_amd64.whl", hash = "sha256:49c32f216c17148695ca0e02a5c521e28a4ee6c5089f97e34fe24163113722da"}, - {file = "pyrsistent-0.19.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f0774bf48631f3a20471dd7c5989657b639fd2d285b861237ea9e82c36a415a9"}, - {file = "pyrsistent-0.19.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3ab2204234c0ecd8b9368dbd6a53e83c3d4f3cab10ecaf6d0e772f456c442393"}, - {file = "pyrsistent-0.19.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e42296a09e83028b3476f7073fcb69ffebac0e66dbbfd1bd847d61f74db30f19"}, - {file = "pyrsistent-0.19.3-cp311-cp311-win32.whl", hash = "sha256:64220c429e42a7150f4bfd280f6f4bb2850f95956bde93c6fda1b70507af6ef3"}, - {file = "pyrsistent-0.19.3-cp311-cp311-win_amd64.whl", hash = "sha256:016ad1afadf318eb7911baa24b049909f7f3bb2c5b1ed7b6a8f21db21ea3faa8"}, - {file = "pyrsistent-0.19.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c4db1bd596fefd66b296a3d5d943c94f4fac5bcd13e99bffe2ba6a759d959a28"}, - {file = "pyrsistent-0.19.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aeda827381f5e5d65cced3024126529ddc4289d944f75e090572c77ceb19adbf"}, - {file = "pyrsistent-0.19.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:42ac0b2f44607eb92ae88609eda931a4f0dfa03038c44c772e07f43e738bcac9"}, - {file = "pyrsistent-0.19.3-cp37-cp37m-win32.whl", hash = "sha256:e8f2b814a3dc6225964fa03d8582c6e0b6650d68a232df41e3cc1b66a5d2f8d1"}, - {file = "pyrsistent-0.19.3-cp37-cp37m-win_amd64.whl", hash = "sha256:c9bb60a40a0ab9aba40a59f68214eed5a29c6274c83b2cc206a359c4a89fa41b"}, - {file = "pyrsistent-0.19.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:a2471f3f8693101975b1ff85ffd19bb7ca7dd7c38f8a81701f67d6b4f97b87d8"}, - {file = "pyrsistent-0.19.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc5d149f31706762c1f8bda2e8c4f8fead6e80312e3692619a75301d3dbb819a"}, - {file = "pyrsistent-0.19.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3311cb4237a341aa52ab8448c27e3a9931e2ee09561ad150ba94e4cfd3fc888c"}, - {file = "pyrsistent-0.19.3-cp38-cp38-win32.whl", hash = "sha256:f0e7c4b2f77593871e918be000b96c8107da48444d57005b6a6bc61fb4331b2c"}, - {file = "pyrsistent-0.19.3-cp38-cp38-win_amd64.whl", hash = "sha256:c147257a92374fde8498491f53ffa8f4822cd70c0d85037e09028e478cababb7"}, - {file = "pyrsistent-0.19.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:b735e538f74ec31378f5a1e3886a26d2ca6351106b4dfde376a26fc32a044edc"}, - {file = "pyrsistent-0.19.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99abb85579e2165bd8522f0c0138864da97847875ecbd45f3e7e2af569bfc6f2"}, - {file = "pyrsistent-0.19.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3a8cb235fa6d3fd7aae6a4f1429bbb1fec1577d978098da1252f0489937786f3"}, - {file = "pyrsistent-0.19.3-cp39-cp39-win32.whl", hash = "sha256:c74bed51f9b41c48366a286395c67f4e894374306b197e62810e0fdaf2364da2"}, - {file = "pyrsistent-0.19.3-cp39-cp39-win_amd64.whl", hash = "sha256:878433581fc23e906d947a6814336eee031a00e6defba224234169ae3d3d6a98"}, - {file = "pyrsistent-0.19.3-py3-none-any.whl", hash = "sha256:ccf0d6bd208f8111179f0c26fdf84ed7c3891982f2edaeae7422575f47e66b64"}, - {file = "pyrsistent-0.19.3.tar.gz", hash = "sha256:1a2994773706bbb4995c31a97bc94f1418314923bd1048c6d964837040376440"}, -] - -[[package]] -name = "returns" -version = "0.19.0" -description = "Make your functions return something meaningful, typed, and safe!" -category = "main" -optional = false -python-versions = ">=3.7,<4.0" -files = [ - {file = "returns-0.19.0-py3-none-any.whl", hash = "sha256:ae3ce9e5165d1218905291b4d5881b4e8a86ca478437bef3b0af1de8df57ec69"}, - {file = "returns-0.19.0.tar.gz", hash = "sha256:4544bb67849c1ef1bbf7823759d433a773959e5b77a8fd06d01fef6d060f2ac5"}, -] - -[package.dependencies] -typing-extensions = ">=4.0,<5.0" - -[[package]] -name = "termcolor" -version = "2.2.0" -description = "ANSI color formatting for output in terminal" -category = "main" -optional = false -python-versions = ">=3.7" -files = [ - {file = "termcolor-2.2.0-py3-none-any.whl", hash = "sha256:91ddd848e7251200eac969846cbae2dacd7d71c2871e92733289e7e3666f48e7"}, - {file = "termcolor-2.2.0.tar.gz", hash = "sha256:dfc8ac3f350788f23b2947b3e6cfa5a53b630b612e6cd8965a015a776020b99a"}, -] - -[package.extras] -tests = ["pytest", "pytest-cov"] - -[[package]] -name = "tomli" -version = "2.0.1" -description = "A lil' TOML parser" -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, - {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, -] - -[[package]] -name = "tomlkit" -version = "0.11.7" -description = "Style preserving TOML library" -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "tomlkit-0.11.7-py3-none-any.whl", hash = "sha256:5325463a7da2ef0c6bbfefb62a3dc883aebe679984709aee32a317907d0a8d3c"}, - {file = "tomlkit-0.11.7.tar.gz", hash = "sha256:f392ef70ad87a672f02519f99967d28a4d3047133e2d1df936511465fbb3791d"}, -] - -[[package]] -name = "typing-extensions" -version = "4.5.0" -description = "Backported and Experimental Type Hints for Python 3.7+" -category = "main" -optional = false -python-versions = ">=3.7" -files = [ - {file = "typing_extensions-4.5.0-py3-none-any.whl", hash = "sha256:fb33085c39dd998ac16d1431ebc293a8b3eedd00fd4a32de0ff79002c19511b4"}, - {file = "typing_extensions-4.5.0.tar.gz", hash = "sha256:5cb5f4a79139d699607b3ef622a1dedafa84e115ab0024e0d9c044a9479ca7cb"}, -] - -[[package]] -name = "wrapt" -version = "1.15.0" -description = "Module for decorators, wrappers and monkey patching." -category = "dev" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" -files = [ - {file = "wrapt-1.15.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:ca1cccf838cd28d5a0883b342474c630ac48cac5df0ee6eacc9c7290f76b11c1"}, - {file = "wrapt-1.15.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:e826aadda3cae59295b95343db8f3d965fb31059da7de01ee8d1c40a60398b29"}, - {file = "wrapt-1.15.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:5fc8e02f5984a55d2c653f5fea93531e9836abbd84342c1d1e17abc4a15084c2"}, - {file = "wrapt-1.15.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:96e25c8603a155559231c19c0349245eeb4ac0096fe3c1d0be5c47e075bd4f46"}, - {file = "wrapt-1.15.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:40737a081d7497efea35ab9304b829b857f21558acfc7b3272f908d33b0d9d4c"}, - {file = "wrapt-1.15.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:f87ec75864c37c4c6cb908d282e1969e79763e0d9becdfe9fe5473b7bb1e5f09"}, - {file = "wrapt-1.15.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:1286eb30261894e4c70d124d44b7fd07825340869945c79d05bda53a40caa079"}, - {file = "wrapt-1.15.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:493d389a2b63c88ad56cdc35d0fa5752daac56ca755805b1b0c530f785767d5e"}, - {file = "wrapt-1.15.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:58d7a75d731e8c63614222bcb21dd992b4ab01a399f1f09dd82af17bbfc2368a"}, - {file = "wrapt-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:21f6d9a0d5b3a207cdf7acf8e58d7d13d463e639f0c7e01d82cdb671e6cb7923"}, - {file = "wrapt-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ce42618f67741d4697684e501ef02f29e758a123aa2d669e2d964ff734ee00ee"}, - {file = "wrapt-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41d07d029dd4157ae27beab04d22b8e261eddfc6ecd64ff7000b10dc8b3a5727"}, - {file = "wrapt-1.15.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54accd4b8bc202966bafafd16e69da9d5640ff92389d33d28555c5fd4f25ccb7"}, - {file = "wrapt-1.15.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2fbfbca668dd15b744418265a9607baa970c347eefd0db6a518aaf0cfbd153c0"}, - {file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:76e9c727a874b4856d11a32fb0b389afc61ce8aaf281ada613713ddeadd1cfec"}, - {file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e20076a211cd6f9b44a6be58f7eeafa7ab5720eb796975d0c03f05b47d89eb90"}, - {file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a74d56552ddbde46c246b5b89199cb3fd182f9c346c784e1a93e4dc3f5ec9975"}, - {file = "wrapt-1.15.0-cp310-cp310-win32.whl", hash = "sha256:26458da5653aa5b3d8dc8b24192f574a58984c749401f98fff994d41d3f08da1"}, - {file = "wrapt-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:75760a47c06b5974aa5e01949bf7e66d2af4d08cb8c1d6516af5e39595397f5e"}, - {file = "wrapt-1.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ba1711cda2d30634a7e452fc79eabcadaffedf241ff206db2ee93dd2c89a60e7"}, - {file = "wrapt-1.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:56374914b132c702aa9aa9959c550004b8847148f95e1b824772d453ac204a72"}, - {file = "wrapt-1.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a89ce3fd220ff144bd9d54da333ec0de0399b52c9ac3d2ce34b569cf1a5748fb"}, - {file = "wrapt-1.15.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3bbe623731d03b186b3d6b0d6f51865bf598587c38d6f7b0be2e27414f7f214e"}, - {file = "wrapt-1.15.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3abbe948c3cbde2689370a262a8d04e32ec2dd4f27103669a45c6929bcdbfe7c"}, - {file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b67b819628e3b748fd3c2192c15fb951f549d0f47c0449af0764d7647302fda3"}, - {file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7eebcdbe3677e58dd4c0e03b4f2cfa346ed4049687d839adad68cc38bb559c92"}, - {file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:74934ebd71950e3db69960a7da29204f89624dde411afbfb3b4858c1409b1e98"}, - {file = "wrapt-1.15.0-cp311-cp311-win32.whl", hash = "sha256:bd84395aab8e4d36263cd1b9308cd504f6cf713b7d6d3ce25ea55670baec5416"}, - {file = "wrapt-1.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:a487f72a25904e2b4bbc0817ce7a8de94363bd7e79890510174da9d901c38705"}, - {file = "wrapt-1.15.0-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:4ff0d20f2e670800d3ed2b220d40984162089a6e2c9646fdb09b85e6f9a8fc29"}, - {file = "wrapt-1.15.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:9ed6aa0726b9b60911f4aed8ec5b8dd7bf3491476015819f56473ffaef8959bd"}, - {file = "wrapt-1.15.0-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:896689fddba4f23ef7c718279e42f8834041a21342d95e56922e1c10c0cc7afb"}, - {file = "wrapt-1.15.0-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:75669d77bb2c071333417617a235324a1618dba66f82a750362eccbe5b61d248"}, - {file = "wrapt-1.15.0-cp35-cp35m-win32.whl", hash = "sha256:fbec11614dba0424ca72f4e8ba3c420dba07b4a7c206c8c8e4e73f2e98f4c559"}, - {file = "wrapt-1.15.0-cp35-cp35m-win_amd64.whl", hash = "sha256:fd69666217b62fa5d7c6aa88e507493a34dec4fa20c5bd925e4bc12fce586639"}, - {file = "wrapt-1.15.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:b0724f05c396b0a4c36a3226c31648385deb6a65d8992644c12a4963c70326ba"}, - {file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bbeccb1aa40ab88cd29e6c7d8585582c99548f55f9b2581dfc5ba68c59a85752"}, - {file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:38adf7198f8f154502883242f9fe7333ab05a5b02de7d83aa2d88ea621f13364"}, - {file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:578383d740457fa790fdf85e6d346fda1416a40549fe8db08e5e9bd281c6a475"}, - {file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:a4cbb9ff5795cd66f0066bdf5947f170f5d63a9274f99bdbca02fd973adcf2a8"}, - {file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:af5bd9ccb188f6a5fdda9f1f09d9f4c86cc8a539bd48a0bfdc97723970348418"}, - {file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:b56d5519e470d3f2fe4aa7585f0632b060d532d0696c5bdfb5e8319e1d0f69a2"}, - {file = "wrapt-1.15.0-cp36-cp36m-win32.whl", hash = "sha256:77d4c1b881076c3ba173484dfa53d3582c1c8ff1f914c6461ab70c8428b796c1"}, - {file = "wrapt-1.15.0-cp36-cp36m-win_amd64.whl", hash = "sha256:077ff0d1f9d9e4ce6476c1a924a3332452c1406e59d90a2cf24aeb29eeac9420"}, - {file = "wrapt-1.15.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5c5aa28df055697d7c37d2099a7bc09f559d5053c3349b1ad0c39000e611d317"}, - {file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3a8564f283394634a7a7054b7983e47dbf39c07712d7b177b37e03f2467a024e"}, - {file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:780c82a41dc493b62fc5884fb1d3a3b81106642c5c5c78d6a0d4cbe96d62ba7e"}, - {file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e169e957c33576f47e21864cf3fc9ff47c223a4ebca8960079b8bd36cb014fd0"}, - {file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b02f21c1e2074943312d03d243ac4388319f2456576b2c6023041c4d57cd7019"}, - {file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f2e69b3ed24544b0d3dbe2c5c0ba5153ce50dcebb576fdc4696d52aa22db6034"}, - {file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d787272ed958a05b2c86311d3a4135d3c2aeea4fc655705f074130aa57d71653"}, - {file = "wrapt-1.15.0-cp37-cp37m-win32.whl", hash = "sha256:02fce1852f755f44f95af51f69d22e45080102e9d00258053b79367d07af39c0"}, - {file = "wrapt-1.15.0-cp37-cp37m-win_amd64.whl", hash = "sha256:abd52a09d03adf9c763d706df707c343293d5d106aea53483e0ec8d9e310ad5e"}, - {file = "wrapt-1.15.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cdb4f085756c96a3af04e6eca7f08b1345e94b53af8921b25c72f096e704e145"}, - {file = "wrapt-1.15.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:230ae493696a371f1dbffaad3dafbb742a4d27a0afd2b1aecebe52b740167e7f"}, - {file = "wrapt-1.15.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63424c681923b9f3bfbc5e3205aafe790904053d42ddcc08542181a30a7a51bd"}, - {file = "wrapt-1.15.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6bcbfc99f55655c3d93feb7ef3800bd5bbe963a755687cbf1f490a71fb7794b"}, - {file = "wrapt-1.15.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c99f4309f5145b93eca6e35ac1a988f0dc0a7ccf9ccdcd78d3c0adf57224e62f"}, - {file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b130fe77361d6771ecf5a219d8e0817d61b236b7d8b37cc045172e574ed219e6"}, - {file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:96177eb5645b1c6985f5c11d03fc2dbda9ad24ec0f3a46dcce91445747e15094"}, - {file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d5fe3e099cf07d0fb5a1e23d399e5d4d1ca3e6dfcbe5c8570ccff3e9208274f7"}, - {file = "wrapt-1.15.0-cp38-cp38-win32.whl", hash = "sha256:abd8f36c99512755b8456047b7be10372fca271bf1467a1caa88db991e7c421b"}, - {file = "wrapt-1.15.0-cp38-cp38-win_amd64.whl", hash = "sha256:b06fa97478a5f478fb05e1980980a7cdf2712015493b44d0c87606c1513ed5b1"}, - {file = "wrapt-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2e51de54d4fb8fb50d6ee8327f9828306a959ae394d3e01a1ba8b2f937747d86"}, - {file = "wrapt-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0970ddb69bba00670e58955f8019bec4a42d1785db3faa043c33d81de2bf843c"}, - {file = "wrapt-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76407ab327158c510f44ded207e2f76b657303e17cb7a572ffe2f5a8a48aa04d"}, - {file = "wrapt-1.15.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cd525e0e52a5ff16653a3fc9e3dd827981917d34996600bbc34c05d048ca35cc"}, - {file = "wrapt-1.15.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d37ac69edc5614b90516807de32d08cb8e7b12260a285ee330955604ed9dd29"}, - {file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:078e2a1a86544e644a68422f881c48b84fef6d18f8c7a957ffd3f2e0a74a0d4a"}, - {file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:2cf56d0e237280baed46f0b5316661da892565ff58309d4d2ed7dba763d984b8"}, - {file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7dc0713bf81287a00516ef43137273b23ee414fe41a3c14be10dd95ed98a2df9"}, - {file = "wrapt-1.15.0-cp39-cp39-win32.whl", hash = "sha256:46ed616d5fb42f98630ed70c3529541408166c22cdfd4540b88d5f21006b0eff"}, - {file = "wrapt-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:eef4d64c650f33347c1f9266fa5ae001440b232ad9b98f1f43dfe7a79435c0a6"}, - {file = "wrapt-1.15.0-py3-none-any.whl", hash = "sha256:64b1df0f83706b4ef4cfb4fb0e4c2669100fd7ecacfb59e091fad300d4e04640"}, - {file = "wrapt-1.15.0.tar.gz", hash = "sha256:d06730c6aed78cee4126234cf2d071e01b44b915e725a6cb439a879ec9754a3a"}, -] - -[metadata] -lock-version = "2.0" -python-versions = "^3.10" -content-hash = "18eb76a106ed41effeddd4dcd8acf90b85b09d7a9e31dd965cb9462c2c7166a9" +[[package]] +name = "astroid" +version = "2.15.2" +description = "An abstract syntax tree for Python with inference support." +category = "dev" +optional = false +python-versions = ">=3.7.2" + +[package.dependencies] +lazy-object-proxy = ">=1.4.0" +typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.11\""} +wrapt = [ + {version = ">=1.11,<2", markers = "python_version < \"3.11\""}, + {version = ">=1.14,<2", markers = "python_version >= \"3.11\""}, +] + +[[package]] +name = "attrs" +version = "22.2.0" +description = "Classes Without Boilerplate" +category = "main" +optional = false +python-versions = ">=3.6" + +[package.extras] +cov = ["attrs", "coverage-enable-subprocess", "coverage[toml] (>=5.3)"] +dev = ["attrs"] +docs = ["furo", "sphinx", "myst-parser", "zope.interface", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier"] +tests = ["attrs", "zope.interface"] +tests-no-zope = ["hypothesis", "pympler", "pytest (>=4.3.0)", "pytest-xdist", "cloudpickle", "mypy (>=0.971,<0.990)", "pytest-mypy-plugins"] +tests_no_zope = ["hypothesis", "pympler", "pytest (>=4.3.0)", "pytest-xdist", "cloudpickle", "mypy (>=0.971,<0.990)", "pytest-mypy-plugins"] + +[[package]] +name = "black" +version = "23.3.0" +description = "The uncompromising code formatter." +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +click = ">=8.0.0" +mypy-extensions = ">=0.4.3" +packaging = ">=22.0" +pathspec = ">=0.9.0" +platformdirs = ">=2" +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} + +[package.extras] +colorama = ["colorama (>=0.4.3)"] +d = ["aiohttp (>=3.7.4)"] +jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] +uvloop = ["uvloop (>=0.15.2)"] + +[[package]] +name = "click" +version = "8.1.3" +description = "Composable command line interface toolkit" +category = "main" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} + +[[package]] +name = "colorama" +version = "0.4.6" +description = "Cross-platform colored terminal text." +category = "main" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" + +[[package]] +name = "dill" +version = "0.3.6" +description = "serialize all of python" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.extras] +graph = ["objgraph (>=1.7.2)"] + +[[package]] +name = "isort" +version = "5.12.0" +description = "A Python utility / library to sort Python imports." +category = "dev" +optional = false +python-versions = ">=3.8.0" + +[package.extras] +colors = ["colorama (>=0.4.3)"] +requirements-deprecated-finder = ["pip-api", "pipreqs"] +pipfile-deprecated-finder = ["pip-shims (>=0.5.2)", "pipreqs", "requirementslib"] +plugins = ["setuptools"] + +[[package]] +name = "jsonschema" +version = "4.17.3" +description = "An implementation of JSON Schema validation for Python" +category = "main" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +attrs = ">=17.4.0" +pyrsistent = ">=0.14.0,<0.17.0 || >0.17.0,<0.17.1 || >0.17.1,<0.17.2 || >0.17.2" + +[package.extras] +format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"] +format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "uri-template", "webcolors (>=1.11)"] + +[[package]] +name = "lazy-object-proxy" +version = "1.9.0" +description = "A fast and thorough lazy object proxy." +category = "dev" +optional = false +python-versions = ">=3.7" + +[[package]] +name = "mccabe" +version = "0.7.0" +description = "McCabe checker, plugin for flake8" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mypy-extensions" +version = "1.0.0" +description = "Type system extensions for programs checked with the mypy type checker." +category = "dev" +optional = false +python-versions = ">=3.5" + +[[package]] +name = "packaging" +version = "23.0" +description = "Core utilities for Python packages" +category = "dev" +optional = false +python-versions = ">=3.7" + +[[package]] +name = "pathspec" +version = "0.11.1" +description = "Utility library for gitignore style pattern matching of file paths." +category = "dev" +optional = false +python-versions = ">=3.7" + +[[package]] +name = "platformdirs" +version = "3.2.0" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.extras] +docs = ["furo (>=2022.12.7)", "proselint (>=0.13)", "sphinx-autodoc-typehints (>=1.22,!=1.23.4)", "sphinx (>=6.1.3)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest-cov (>=4)", "pytest-mock (>=3.10)", "pytest (>=7.2.2)"] + +[[package]] +name = "pylint" +version = "2.17.2" +description = "python code static checker" +category = "dev" +optional = false +python-versions = ">=3.7.2" + +[package.dependencies] +astroid = ">=2.15.2,<=2.17.0-dev0" +colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} +dill = [ + {version = ">=0.2", markers = "python_version < \"3.11\""}, + {version = ">=0.3.6", markers = "python_version >= \"3.11\""}, +] +isort = ">=4.2.5,<6" +mccabe = ">=0.6,<0.8" +platformdirs = ">=2.2.0" +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} +tomlkit = ">=0.10.1" + +[package.extras] +spelling = ["pyenchant (>=3.2,<4.0)"] +testutils = ["gitpython (>3)"] + +[[package]] +name = "pyrsistent" +version = "0.19.3" +description = "Persistent/Functional/Immutable data structures" +category = "main" +optional = false +python-versions = ">=3.7" + +[[package]] +name = "returns" +version = "0.19.0" +description = "Make your functions return something meaningful, typed, and safe!" +category = "main" +optional = false +python-versions = ">=3.7,<4.0" + +[package.dependencies] +typing-extensions = ">=4.0,<5.0" + +[[package]] +name = "termcolor" +version = "2.2.0" +description = "ANSI color formatting for output in terminal" +category = "main" +optional = false +python-versions = ">=3.7" + +[package.extras] +tests = ["pytest", "pytest-cov"] + +[[package]] +name = "tomli" +version = "2.0.1" +description = "A lil' TOML parser" +category = "dev" +optional = false +python-versions = ">=3.7" + +[[package]] +name = "tomlkit" +version = "0.11.7" +description = "Style preserving TOML library" +category = "dev" +optional = false +python-versions = ">=3.7" + +[[package]] +name = "typing-extensions" +version = "4.5.0" +description = "Backported and Experimental Type Hints for Python 3.7+" +category = "main" +optional = false +python-versions = ">=3.7" + +[[package]] +name = "wrapt" +version = "1.15.0" +description = "Module for decorators, wrappers and monkey patching." +category = "dev" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" + +[metadata] +lock-version = "1.1" +python-versions = "^3.10" +content-hash = "d2427826ed7e4bc10b073aee9adaa3e41c745f3305da6026a8e4abbbb73bb87e" + +[metadata.files] +astroid = [] +attrs = [] +black = [] +click = [] +colorama = [] +dill = [] +isort = [] +jsonschema = [] +lazy-object-proxy = [] +mccabe = [] +mypy-extensions = [] +packaging = [] +pathspec = [] +platformdirs = [] +pylint = [] +pyrsistent = [] +returns = [] +termcolor = [] +tomli = [] +tomlkit = [] +typing-extensions = [] +wrapt = [] From b921d94b981479d7e466a63da39811dbb68abcad Mon Sep 17 00:00:00 2001 From: Simeon Widdis Date: Mon, 3 Apr 2023 11:26:50 -0700 Subject: [PATCH 14/40] Add install to poetry steps Signed-off-by: Simeon Widdis --- .github/workflows/python-poetry.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/python-poetry.yml b/.github/workflows/python-poetry.yml index 6f46b890f..acebc5421 100644 --- a/.github/workflows/python-poetry.yml +++ b/.github/workflows/python-poetry.yml @@ -20,4 +20,4 @@ jobs: with: poetry-version: ${{ matrix.poetry-version }} - name: Run Integrations CLI unit tests - run: cd scripts/integrations-cli && poetry run python -m unittest \ No newline at end of file + run: cd scripts/integrations-cli && poetry install && poetry run python -m unittest \ No newline at end of file From a7fa6f864044934a1a7c08d788bc1ee4fea67f7e Mon Sep 17 00:00:00 2001 From: Simeon Widdis Date: Mon, 3 Apr 2023 17:23:33 -0700 Subject: [PATCH 15/40] Refactor project with builds and scripts Signed-off-by: Simeon Widdis --- scripts/integrations-cli/README.md | 49 +++++++++++++++++++ .../helpers/__init__.py | 0 .../{ => integrations_cli}/helpers/catalog.py | 0 .../helpers/constants.py | 0 .../{ => integrations_cli}/helpers/create.py | 0 .../helpers/validate.py | 0 .../main.py} | 2 +- scripts/integrations-cli/pyproject.toml | 5 ++ scripts/integrations-cli/scripts.py | 17 +++++++ .../integrations-cli/tests/test_validate.py | 6 +-- 10 files changed, 75 insertions(+), 4 deletions(-) create mode 100644 scripts/integrations-cli/README.md rename scripts/integrations-cli/{ => integrations_cli}/helpers/__init__.py (100%) rename scripts/integrations-cli/{ => integrations_cli}/helpers/catalog.py (100%) rename scripts/integrations-cli/{ => integrations_cli}/helpers/constants.py (100%) rename scripts/integrations-cli/{ => integrations_cli}/helpers/create.py (100%) rename scripts/integrations-cli/{ => integrations_cli}/helpers/validate.py (100%) rename scripts/integrations-cli/{integrations-cli.py => integrations_cli/main.py} (99%) create mode 100644 scripts/integrations-cli/scripts.py diff --git a/scripts/integrations-cli/README.md b/scripts/integrations-cli/README.md new file mode 100644 index 000000000..6de04630b --- /dev/null +++ b/scripts/integrations-cli/README.md @@ -0,0 +1,49 @@ +# Integrations CLI + +## Description + +This is a CLI tool for creating, validating, and maintaining OpenSearch Dashboard Integrations. +The tool has three main functions: + +- `create` a new integration with a specified configuration. +- `check` an integration for validity +- `package` an integration to be upload to an OpenSearch Integrations instance + +## Installation + +The project is managed with [Poetry](https://python-poetry.org/). +After installing Poetry, install dependencies: + +```sh +$ poetry install +Installing dependencies from lock file +``` + +## Usage + +The CLI can be run with: + +```sh +$ poetry run cli +Usage: cli.cmd [OPTIONS] COMMAND [ARGS]... +``` + +If you don't want to prefix everything + +## Development + +For development, there are a few scripts to help: + +```sh +$ poetry run test +... +OK + +$ poetry run format +... +All done! +``` + +## License + +This project, like the rest of the OpenSearch projects, is licensed under the Apache 2.0 License. diff --git a/scripts/integrations-cli/helpers/__init__.py b/scripts/integrations-cli/integrations_cli/helpers/__init__.py similarity index 100% rename from scripts/integrations-cli/helpers/__init__.py rename to scripts/integrations-cli/integrations_cli/helpers/__init__.py diff --git a/scripts/integrations-cli/helpers/catalog.py b/scripts/integrations-cli/integrations_cli/helpers/catalog.py similarity index 100% rename from scripts/integrations-cli/helpers/catalog.py rename to scripts/integrations-cli/integrations_cli/helpers/catalog.py diff --git a/scripts/integrations-cli/helpers/constants.py b/scripts/integrations-cli/integrations_cli/helpers/constants.py similarity index 100% rename from scripts/integrations-cli/helpers/constants.py rename to scripts/integrations-cli/integrations_cli/helpers/constants.py diff --git a/scripts/integrations-cli/helpers/create.py b/scripts/integrations-cli/integrations_cli/helpers/create.py similarity index 100% rename from scripts/integrations-cli/helpers/create.py rename to scripts/integrations-cli/integrations_cli/helpers/create.py diff --git a/scripts/integrations-cli/helpers/validate.py b/scripts/integrations-cli/integrations_cli/helpers/validate.py similarity index 100% rename from scripts/integrations-cli/helpers/validate.py rename to scripts/integrations-cli/integrations_cli/helpers/validate.py diff --git a/scripts/integrations-cli/integrations-cli.py b/scripts/integrations-cli/integrations_cli/main.py similarity index 99% rename from scripts/integrations-cli/integrations-cli.py rename to scripts/integrations-cli/integrations_cli/main.py index aea7f8f3a..e7e6c170e 100644 --- a/scripts/integrations-cli/integrations-cli.py +++ b/scripts/integrations-cli/integrations_cli/main.py @@ -8,7 +8,7 @@ from returns.result import Result from termcolor import colored -import helpers +import integrations_cli.helpers as helpers @click.group() diff --git a/scripts/integrations-cli/pyproject.toml b/scripts/integrations-cli/pyproject.toml index ace8da909..3403f6ad7 100644 --- a/scripts/integrations-cli/pyproject.toml +++ b/scripts/integrations-cli/pyproject.toml @@ -5,6 +5,11 @@ description = "CLI for managing OpenSearch Integrations" authors = ["Simeon Widdis "] license = "Apache-2.0" +[tool.poetry.scripts] +cli = "integrations_cli.main:integrations_cli" +test = "scripts:test" +format = "scripts:format" + [tool.isort] profile = "black" diff --git a/scripts/integrations-cli/scripts.py b/scripts/integrations-cli/scripts.py new file mode 100644 index 000000000..f13d3d394 --- /dev/null +++ b/scripts/integrations-cli/scripts.py @@ -0,0 +1,17 @@ +import subprocess + + +def test(): + """ + Run all unittests. Equivalent to: + `poetry run python -u -m unittest discover` + """ + subprocess.run(["python", "-u", "-m", "unittest", "discover"]) + + +def format(): + """ + Reformat all code. Equivalent to: + `poetry run black .` + """ + subprocess.run(["black", "."]) diff --git a/scripts/integrations-cli/tests/test_validate.py b/scripts/integrations-cli/tests/test_validate.py index de2e7bb6d..c6498a8b8 100644 --- a/scripts/integrations-cli/tests/test_validate.py +++ b/scripts/integrations-cli/tests/test_validate.py @@ -4,9 +4,9 @@ import jsonschema from returns.pipeline import is_successful -import helpers.constants as constants -import helpers.validate as validate -from helpers.catalog import _load_catalog_file +import integrations_cli.helpers.constants as constants +import integrations_cli.helpers.validate as validate +from integrations_cli.helpers.catalog import _load_catalog_file class TestSchemas(unittest.TestCase): From 7592d2f44be26521b90c4a736ea8077a6aad60cf Mon Sep 17 00:00:00 2001 From: Simeon Widdis Date: Mon, 10 Apr 2023 15:08:11 -0700 Subject: [PATCH 16/40] Fix catalog schema Signed-off-by: Simeon Widdis --- src/main/resources/schema/system/catalog.schema | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/resources/schema/system/catalog.schema b/src/main/resources/schema/system/catalog.schema index 2c8a8c7f9..c7a3e7357 100644 --- a/src/main/resources/schema/system/catalog.schema +++ b/src/main/resources/schema/system/catalog.schema @@ -4,7 +4,7 @@ "definitions": { "Catalog": { "type": "object", - "additionalProperties": false, + "additionalProperties": true, "properties": { "catalog": { "type": "string" @@ -36,7 +36,7 @@ }, "Category": { "type": "object", - "additionalProperties": false, + "additionalProperties": true, "properties": { "category": { "type": "string" @@ -68,7 +68,7 @@ }, "Component": { "type": "object", - "additionalProperties": false, + "additionalProperties": true, "properties": { "component": { "type": "string" From 74747bb5a822bd6fd716fbdb1a8749236bd24631 Mon Sep 17 00:00:00 2001 From: Simeon Widdis Date: Mon, 10 Apr 2023 15:48:35 -0700 Subject: [PATCH 17/40] Add better component handling Signed-off-by: Simeon Widdis --- .../integrations_cli/helpers/create.py | 21 +- .../integrations-cli/integrations_cli/main.py | 19 +- scripts/integrations-cli/poetry.lock | 930 ++++++++++++------ scripts/integrations-cli/pyproject.toml | 1 + .../template-dashboards/http.ndjson | 10 + 5 files changed, 696 insertions(+), 285 deletions(-) create mode 100644 scripts/integrations-cli/template-dashboards/http.ndjson diff --git a/scripts/integrations-cli/integrations_cli/helpers/create.py b/scripts/integrations-cli/integrations_cli/helpers/create.py index 233d9eeb7..de09fc647 100644 --- a/scripts/integrations-cli/integrations_cli/helpers/create.py +++ b/scripts/integrations-cli/integrations_cli/helpers/create.py @@ -3,6 +3,7 @@ import re from copy import deepcopy from urllib import parse +import requests from .constants import DEFAULT_CONFIG from .validate import validate_config @@ -12,6 +13,8 @@ class IntegrationBuilder: def __init__(self): self.path = None self.config = deepcopy(DEFAULT_CONFIG) + self.dashboards = [] + self.mappings = dict() def with_name(self, name: str) -> "IntegrationBuilder": self.config["template-name"] = name @@ -49,13 +52,29 @@ def with_repository(self, repo_url: str) -> "IntegrationBuilder": return self def with_component(self, component: dict) -> "IntegrationBuilder": - self.config["components"].append(component) + ## TODO make robust + self.config["components"].append(component["component"]) + url = component["url"].replace("github.com", "raw.githubusercontent.com").replace("/tree", "") + ".mapping" + mapping = requests.get(url).json() + self.mappings[url.split("/")[-1]] = mapping + return self + + def with_dashboard(self, component: str) -> "IntegrationBuilder": + ## TODO make robust + self.dashboards.append(component) return self def build(self): assert self.path is not None os.makedirs(self.path, exist_ok=True) files = {"config.json": validate_config(self.config).unwrap()} + for fname, mapping in self.mappings.items(): + files[f"schema/{fname}"] = mapping # TODO validate for filename, data in files.items(): with open(os.path.join(self.path, filename), "w", encoding="utf-8") as file: json.dump(data, file, ensure_ascii=False, indent=2) + for dashboard in self.dashboards: + print(os.path.abspath(".")) + with open(dashboard, "r") as fin: + with open(os.path.join(self.path, "assets/display", dashboard.split('/')[-1]), "w") as fout: + fout.write(fin.read()) diff --git a/scripts/integrations-cli/integrations_cli/main.py b/scripts/integrations-cli/integrations_cli/main.py index e7e6c170e..dc43bb3e6 100644 --- a/scripts/integrations-cli/integrations_cli/main.py +++ b/scripts/integrations-cli/integrations_cli/main.py @@ -10,6 +10,10 @@ import integrations_cli.helpers as helpers +available_templates = { + "http": "template-dashboards/http.ndjson" +} + @click.group() def integrations_cli(): @@ -23,12 +27,21 @@ def do_add_component(builder: helpers.IntegrationBuilder) -> bool: for category in manager.catalog["categories"]: click.echo(f"- Category {category['category']}") for component in category["components"]: - click.echo(f" - {component['component']}: {component['description']}") + desc = component["description"] + desc = desc if len(desc) < 50 else desc[:47] + "..." + click.echo(f" - {component['component']}: {desc}") choices[component["component"]] = component component = click.prompt( "Select component", type=click.Choice(list(choices)), show_choices=False ) - builder.with_component(component) + builder = builder.with_component(choices[component]) + if component in available_templates: + if click.prompt( + f"A pre-made template dashboard for component `{component}` was detected. Include it? (y/n)", + type=click.Choice(["y", "n"]), + show_choices=False + ) == "y": + builder.with_dashboard(available_templates[component]) return ( click.prompt( "Configure another component? (y/n)", @@ -49,7 +62,7 @@ def create(name: str): raise click.ClickException( f"destination path '{integration_path}' exists and is non-empty" ) - for subdir in ["assets", "info", "samples", "schema", "test"]: + for subdir in ["assets", "schema", "assets/display"]: os.makedirs(os.path.join(integration_path, subdir)) builder = helpers.IntegrationBuilder().with_name(name).with_path(integration_path) click.prompt("Schema version", default="1.0.0", type=builder.with_schema_version) diff --git a/scripts/integrations-cli/poetry.lock b/scripts/integrations-cli/poetry.lock index e324e602a..f599c5e81 100644 --- a/scripts/integrations-cli/poetry.lock +++ b/scripts/integrations-cli/poetry.lock @@ -1,281 +1,649 @@ -[[package]] -name = "astroid" -version = "2.15.2" -description = "An abstract syntax tree for Python with inference support." -category = "dev" -optional = false -python-versions = ">=3.7.2" - -[package.dependencies] -lazy-object-proxy = ">=1.4.0" -typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.11\""} -wrapt = [ - {version = ">=1.11,<2", markers = "python_version < \"3.11\""}, - {version = ">=1.14,<2", markers = "python_version >= \"3.11\""}, -] - -[[package]] -name = "attrs" -version = "22.2.0" -description = "Classes Without Boilerplate" -category = "main" -optional = false -python-versions = ">=3.6" - -[package.extras] -cov = ["attrs", "coverage-enable-subprocess", "coverage[toml] (>=5.3)"] -dev = ["attrs"] -docs = ["furo", "sphinx", "myst-parser", "zope.interface", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier"] -tests = ["attrs", "zope.interface"] -tests-no-zope = ["hypothesis", "pympler", "pytest (>=4.3.0)", "pytest-xdist", "cloudpickle", "mypy (>=0.971,<0.990)", "pytest-mypy-plugins"] -tests_no_zope = ["hypothesis", "pympler", "pytest (>=4.3.0)", "pytest-xdist", "cloudpickle", "mypy (>=0.971,<0.990)", "pytest-mypy-plugins"] - -[[package]] -name = "black" -version = "23.3.0" -description = "The uncompromising code formatter." -category = "dev" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -click = ">=8.0.0" -mypy-extensions = ">=0.4.3" -packaging = ">=22.0" -pathspec = ">=0.9.0" -platformdirs = ">=2" -tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} - -[package.extras] -colorama = ["colorama (>=0.4.3)"] -d = ["aiohttp (>=3.7.4)"] -jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] -uvloop = ["uvloop (>=0.15.2)"] - -[[package]] -name = "click" -version = "8.1.3" -description = "Composable command line interface toolkit" -category = "main" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -colorama = {version = "*", markers = "platform_system == \"Windows\""} - -[[package]] -name = "colorama" -version = "0.4.6" -description = "Cross-platform colored terminal text." -category = "main" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" - -[[package]] -name = "dill" -version = "0.3.6" -description = "serialize all of python" -category = "dev" -optional = false -python-versions = ">=3.7" - -[package.extras] -graph = ["objgraph (>=1.7.2)"] - -[[package]] -name = "isort" -version = "5.12.0" -description = "A Python utility / library to sort Python imports." -category = "dev" -optional = false -python-versions = ">=3.8.0" - -[package.extras] -colors = ["colorama (>=0.4.3)"] -requirements-deprecated-finder = ["pip-api", "pipreqs"] -pipfile-deprecated-finder = ["pip-shims (>=0.5.2)", "pipreqs", "requirementslib"] -plugins = ["setuptools"] - -[[package]] -name = "jsonschema" -version = "4.17.3" -description = "An implementation of JSON Schema validation for Python" -category = "main" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -attrs = ">=17.4.0" -pyrsistent = ">=0.14.0,<0.17.0 || >0.17.0,<0.17.1 || >0.17.1,<0.17.2 || >0.17.2" - -[package.extras] -format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"] -format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "uri-template", "webcolors (>=1.11)"] - -[[package]] -name = "lazy-object-proxy" -version = "1.9.0" -description = "A fast and thorough lazy object proxy." -category = "dev" -optional = false -python-versions = ">=3.7" - -[[package]] -name = "mccabe" -version = "0.7.0" -description = "McCabe checker, plugin for flake8" -category = "dev" -optional = false -python-versions = ">=3.6" - -[[package]] -name = "mypy-extensions" -version = "1.0.0" -description = "Type system extensions for programs checked with the mypy type checker." -category = "dev" -optional = false -python-versions = ">=3.5" - -[[package]] -name = "packaging" -version = "23.0" -description = "Core utilities for Python packages" -category = "dev" -optional = false -python-versions = ">=3.7" - -[[package]] -name = "pathspec" -version = "0.11.1" -description = "Utility library for gitignore style pattern matching of file paths." -category = "dev" -optional = false -python-versions = ">=3.7" - -[[package]] -name = "platformdirs" -version = "3.2.0" -description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." -category = "dev" -optional = false -python-versions = ">=3.7" - -[package.extras] -docs = ["furo (>=2022.12.7)", "proselint (>=0.13)", "sphinx-autodoc-typehints (>=1.22,!=1.23.4)", "sphinx (>=6.1.3)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest-cov (>=4)", "pytest-mock (>=3.10)", "pytest (>=7.2.2)"] - -[[package]] -name = "pylint" -version = "2.17.2" -description = "python code static checker" -category = "dev" -optional = false -python-versions = ">=3.7.2" - -[package.dependencies] -astroid = ">=2.15.2,<=2.17.0-dev0" -colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} -dill = [ - {version = ">=0.2", markers = "python_version < \"3.11\""}, - {version = ">=0.3.6", markers = "python_version >= \"3.11\""}, -] -isort = ">=4.2.5,<6" -mccabe = ">=0.6,<0.8" -platformdirs = ">=2.2.0" -tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} -tomlkit = ">=0.10.1" - -[package.extras] -spelling = ["pyenchant (>=3.2,<4.0)"] -testutils = ["gitpython (>3)"] - -[[package]] -name = "pyrsistent" -version = "0.19.3" -description = "Persistent/Functional/Immutable data structures" -category = "main" -optional = false -python-versions = ">=3.7" - -[[package]] -name = "returns" -version = "0.19.0" -description = "Make your functions return something meaningful, typed, and safe!" -category = "main" -optional = false -python-versions = ">=3.7,<4.0" - -[package.dependencies] -typing-extensions = ">=4.0,<5.0" - -[[package]] -name = "termcolor" -version = "2.2.0" -description = "ANSI color formatting for output in terminal" -category = "main" -optional = false -python-versions = ">=3.7" - -[package.extras] -tests = ["pytest", "pytest-cov"] - -[[package]] -name = "tomli" -version = "2.0.1" -description = "A lil' TOML parser" -category = "dev" -optional = false -python-versions = ">=3.7" - -[[package]] -name = "tomlkit" -version = "0.11.7" -description = "Style preserving TOML library" -category = "dev" -optional = false -python-versions = ">=3.7" - -[[package]] -name = "typing-extensions" -version = "4.5.0" -description = "Backported and Experimental Type Hints for Python 3.7+" -category = "main" -optional = false -python-versions = ">=3.7" - -[[package]] -name = "wrapt" -version = "1.15.0" -description = "Module for decorators, wrappers and monkey patching." -category = "dev" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" - -[metadata] -lock-version = "1.1" -python-versions = "^3.10" -content-hash = "d2427826ed7e4bc10b073aee9adaa3e41c745f3305da6026a8e4abbbb73bb87e" - -[metadata.files] -astroid = [] -attrs = [] -black = [] -click = [] -colorama = [] -dill = [] -isort = [] -jsonschema = [] -lazy-object-proxy = [] -mccabe = [] -mypy-extensions = [] -packaging = [] -pathspec = [] -platformdirs = [] -pylint = [] -pyrsistent = [] -returns = [] -termcolor = [] -tomli = [] -tomlkit = [] -typing-extensions = [] -wrapt = [] +# This file is automatically @generated by Poetry 1.4.1 and should not be changed by hand. + +[[package]] +name = "astroid" +version = "2.15.2" +description = "An abstract syntax tree for Python with inference support." +category = "dev" +optional = false +python-versions = ">=3.7.2" +files = [ + {file = "astroid-2.15.2-py3-none-any.whl", hash = "sha256:dea89d9f99f491c66ac9c04ebddf91e4acf8bd711722175fe6245c0725cc19bb"}, + {file = "astroid-2.15.2.tar.gz", hash = "sha256:6e61b85c891ec53b07471aec5878f4ac6446a41e590ede0f2ce095f39f7d49dd"}, +] + +[package.dependencies] +lazy-object-proxy = ">=1.4.0" +typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.11\""} +wrapt = [ + {version = ">=1.11,<2", markers = "python_version < \"3.11\""}, + {version = ">=1.14,<2", markers = "python_version >= \"3.11\""}, +] + +[[package]] +name = "attrs" +version = "22.2.0" +description = "Classes Without Boilerplate" +category = "main" +optional = false +python-versions = ">=3.6" +files = [ + {file = "attrs-22.2.0-py3-none-any.whl", hash = "sha256:29e95c7f6778868dbd49170f98f8818f78f3dc5e0e37c0b1f474e3561b240836"}, + {file = "attrs-22.2.0.tar.gz", hash = "sha256:c9227bfc2f01993c03f68db37d1d15c9690188323c067c641f1a35ca58185f99"}, +] + +[package.extras] +cov = ["attrs[tests]", "coverage-enable-subprocess", "coverage[toml] (>=5.3)"] +dev = ["attrs[docs,tests]"] +docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope.interface"] +tests = ["attrs[tests-no-zope]", "zope.interface"] +tests-no-zope = ["cloudpickle", "cloudpickle", "hypothesis", "hypothesis", "mypy (>=0.971,<0.990)", "mypy (>=0.971,<0.990)", "pympler", "pympler", "pytest (>=4.3.0)", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-mypy-plugins", "pytest-xdist[psutil]", "pytest-xdist[psutil]"] + +[[package]] +name = "black" +version = "23.3.0" +description = "The uncompromising code formatter." +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "black-23.3.0-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:0945e13506be58bf7db93ee5853243eb368ace1c08a24c65ce108986eac65915"}, + {file = "black-23.3.0-cp310-cp310-macosx_10_16_universal2.whl", hash = "sha256:67de8d0c209eb5b330cce2469503de11bca4085880d62f1628bd9972cc3366b9"}, + {file = "black-23.3.0-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:7c3eb7cea23904399866c55826b31c1f55bbcd3890ce22ff70466b907b6775c2"}, + {file = "black-23.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:32daa9783106c28815d05b724238e30718f34155653d4d6e125dc7daec8e260c"}, + {file = "black-23.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:35d1381d7a22cc5b2be2f72c7dfdae4072a3336060635718cc7e1ede24221d6c"}, + {file = "black-23.3.0-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:a8a968125d0a6a404842fa1bf0b349a568634f856aa08ffaff40ae0dfa52e7c6"}, + {file = "black-23.3.0-cp311-cp311-macosx_10_16_universal2.whl", hash = "sha256:c7ab5790333c448903c4b721b59c0d80b11fe5e9803d8703e84dcb8da56fec1b"}, + {file = "black-23.3.0-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:a6f6886c9869d4daae2d1715ce34a19bbc4b95006d20ed785ca00fa03cba312d"}, + {file = "black-23.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f3c333ea1dd6771b2d3777482429864f8e258899f6ff05826c3a4fcc5ce3f70"}, + {file = "black-23.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:11c410f71b876f961d1de77b9699ad19f939094c3a677323f43d7a29855fe326"}, + {file = "black-23.3.0-cp37-cp37m-macosx_10_16_x86_64.whl", hash = "sha256:1d06691f1eb8de91cd1b322f21e3bfc9efe0c7ca1f0e1eb1db44ea367dff656b"}, + {file = "black-23.3.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50cb33cac881766a5cd9913e10ff75b1e8eb71babf4c7104f2e9c52da1fb7de2"}, + {file = "black-23.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:e114420bf26b90d4b9daa597351337762b63039752bdf72bf361364c1aa05925"}, + {file = "black-23.3.0-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:48f9d345675bb7fbc3dd85821b12487e1b9a75242028adad0333ce36ed2a6d27"}, + {file = "black-23.3.0-cp38-cp38-macosx_10_16_universal2.whl", hash = "sha256:714290490c18fb0126baa0fca0a54ee795f7502b44177e1ce7624ba1c00f2331"}, + {file = "black-23.3.0-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:064101748afa12ad2291c2b91c960be28b817c0c7eaa35bec09cc63aa56493c5"}, + {file = "black-23.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:562bd3a70495facf56814293149e51aa1be9931567474993c7942ff7d3533961"}, + {file = "black-23.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:e198cf27888ad6f4ff331ca1c48ffc038848ea9f031a3b40ba36aced7e22f2c8"}, + {file = "black-23.3.0-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:3238f2aacf827d18d26db07524e44741233ae09a584273aa059066d644ca7b30"}, + {file = "black-23.3.0-cp39-cp39-macosx_10_16_universal2.whl", hash = "sha256:f0bd2f4a58d6666500542b26354978218a9babcdc972722f4bf90779524515f3"}, + {file = "black-23.3.0-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:92c543f6854c28a3c7f39f4d9b7694f9a6eb9d3c5e2ece488c327b6e7ea9b266"}, + {file = "black-23.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a150542a204124ed00683f0db1f5cf1c2aaaa9cc3495b7a3b5976fb136090ab"}, + {file = "black-23.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:6b39abdfb402002b8a7d030ccc85cf5afff64ee90fa4c5aebc531e3ad0175ddb"}, + {file = "black-23.3.0-py3-none-any.whl", hash = "sha256:ec751418022185b0c1bb7d7736e6933d40bbb14c14a0abcf9123d1b159f98dd4"}, + {file = "black-23.3.0.tar.gz", hash = "sha256:1c7b8d606e728a41ea1ccbd7264677e494e87cf630e399262ced92d4a8dac940"}, +] + +[package.dependencies] +click = ">=8.0.0" +mypy-extensions = ">=0.4.3" +packaging = ">=22.0" +pathspec = ">=0.9.0" +platformdirs = ">=2" +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} + +[package.extras] +colorama = ["colorama (>=0.4.3)"] +d = ["aiohttp (>=3.7.4)"] +jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] +uvloop = ["uvloop (>=0.15.2)"] + +[[package]] +name = "certifi" +version = "2022.12.7" +description = "Python package for providing Mozilla's CA Bundle." +category = "main" +optional = false +python-versions = ">=3.6" +files = [ + {file = "certifi-2022.12.7-py3-none-any.whl", hash = "sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18"}, + {file = "certifi-2022.12.7.tar.gz", hash = "sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3"}, +] + +[[package]] +name = "charset-normalizer" +version = "3.1.0" +description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +category = "main" +optional = false +python-versions = ">=3.7.0" +files = [ + {file = "charset-normalizer-3.1.0.tar.gz", hash = "sha256:34e0a2f9c370eb95597aae63bf85eb5e96826d81e3dcf88b8886012906f509b5"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e0ac8959c929593fee38da1c2b64ee9778733cdf03c482c9ff1d508b6b593b2b"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d7fc3fca01da18fbabe4625d64bb612b533533ed10045a2ac3dd194bfa656b60"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:04eefcee095f58eaabe6dc3cc2262f3bcd776d2c67005880894f447b3f2cb9c1"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20064ead0717cf9a73a6d1e779b23d149b53daf971169289ed2ed43a71e8d3b0"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1435ae15108b1cb6fffbcea2af3d468683b7afed0169ad718451f8db5d1aff6f"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c84132a54c750fda57729d1e2599bb598f5fa0344085dbde5003ba429a4798c0"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75f2568b4189dda1c567339b48cba4ac7384accb9c2a7ed655cd86b04055c795"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:11d3bcb7be35e7b1bba2c23beedac81ee893ac9871d0ba79effc7fc01167db6c"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:891cf9b48776b5c61c700b55a598621fdb7b1e301a550365571e9624f270c203"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:5f008525e02908b20e04707a4f704cd286d94718f48bb33edddc7d7b584dddc1"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:b06f0d3bf045158d2fb8837c5785fe9ff9b8c93358be64461a1089f5da983137"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:49919f8400b5e49e961f320c735388ee686a62327e773fa5b3ce6721f7e785ce"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:22908891a380d50738e1f978667536f6c6b526a2064156203d418f4856d6e86a"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-win32.whl", hash = "sha256:12d1a39aa6b8c6f6248bb54550efcc1c38ce0d8096a146638fd4738e42284448"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:65ed923f84a6844de5fd29726b888e58c62820e0769b76565480e1fdc3d062f8"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9a3267620866c9d17b959a84dd0bd2d45719b817245e49371ead79ed4f710d19"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6734e606355834f13445b6adc38b53c0fd45f1a56a9ba06c2058f86893ae8017"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f8303414c7b03f794347ad062c0516cee0e15f7a612abd0ce1e25caf6ceb47df"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aaf53a6cebad0eae578f062c7d462155eada9c172bd8c4d250b8c1d8eb7f916a"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3dc5b6a8ecfdc5748a7e429782598e4f17ef378e3e272eeb1340ea57c9109f41"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e1b25e3ad6c909f398df8921780d6a3d120d8c09466720226fc621605b6f92b1"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ca564606d2caafb0abe6d1b5311c2649e8071eb241b2d64e75a0d0065107e62"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b82fab78e0b1329e183a65260581de4375f619167478dddab510c6c6fb04d9b6"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bd7163182133c0c7701b25e604cf1611c0d87712e56e88e7ee5d72deab3e76b5"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:11d117e6c63e8f495412d37e7dc2e2fff09c34b2d09dbe2bee3c6229577818be"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:cf6511efa4801b9b38dc5546d7547d5b5c6ef4b081c60b23e4d941d0eba9cbeb"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:abc1185d79f47c0a7aaf7e2412a0eb2c03b724581139193d2d82b3ad8cbb00ac"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cb7b2ab0188829593b9de646545175547a70d9a6e2b63bf2cd87a0a391599324"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-win32.whl", hash = "sha256:c36bcbc0d5174a80d6cccf43a0ecaca44e81d25be4b7f90f0ed7bcfbb5a00909"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:cca4def576f47a09a943666b8f829606bcb17e2bc2d5911a46c8f8da45f56755"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0c95f12b74681e9ae127728f7e5409cbbef9cd914d5896ef238cc779b8152373"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fca62a8301b605b954ad2e9c3666f9d97f63872aa4efcae5492baca2056b74ab"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac0aa6cd53ab9a31d397f8303f92c42f534693528fafbdb997c82bae6e477ad9"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c3af8e0f07399d3176b179f2e2634c3ce9c1301379a6b8c9c9aeecd481da494f"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a5fc78f9e3f501a1614a98f7c54d3969f3ad9bba8ba3d9b438c3bc5d047dd28"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:628c985afb2c7d27a4800bfb609e03985aaecb42f955049957814e0491d4006d"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:74db0052d985cf37fa111828d0dd230776ac99c740e1a758ad99094be4f1803d"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:1e8fcdd8f672a1c4fc8d0bd3a2b576b152d2a349782d1eb0f6b8e52e9954731d"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:04afa6387e2b282cf78ff3dbce20f0cc071c12dc8f685bd40960cc68644cfea6"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:dd5653e67b149503c68c4018bf07e42eeed6b4e956b24c00ccdf93ac79cdff84"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d2686f91611f9e17f4548dbf050e75b079bbc2a82be565832bc8ea9047b61c8c"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-win32.whl", hash = "sha256:4155b51ae05ed47199dc5b2a4e62abccb274cee6b01da5b895099b61b1982974"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:322102cdf1ab682ecc7d9b1c5eed4ec59657a65e1c146a0da342b78f4112db23"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e633940f28c1e913615fd624fcdd72fdba807bf53ea6925d6a588e84e1151531"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3a06f32c9634a8705f4ca9946d667609f52cf130d5548881401f1eb2c39b1e2c"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7381c66e0561c5757ffe616af869b916c8b4e42b367ab29fedc98481d1e74e14"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3573d376454d956553c356df45bb824262c397c6e26ce43e8203c4c540ee0acb"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e89df2958e5159b811af9ff0f92614dabf4ff617c03a4c1c6ff53bf1c399e0e1"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:78cacd03e79d009d95635e7d6ff12c21eb89b894c354bd2b2ed0b4763373693b"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de5695a6f1d8340b12a5d6d4484290ee74d61e467c39ff03b39e30df62cf83a0"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1c60b9c202d00052183c9be85e5eaf18a4ada0a47d188a83c8f5c5b23252f649"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f645caaf0008bacf349875a974220f1f1da349c5dbe7c4ec93048cdc785a3326"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ea9f9c6034ea2d93d9147818f17c2a0860d41b71c38b9ce4d55f21b6f9165a11"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:80d1543d58bd3d6c271b66abf454d437a438dff01c3e62fdbcd68f2a11310d4b"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:73dc03a6a7e30b7edc5b01b601e53e7fc924b04e1835e8e407c12c037e81adbd"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6f5c2e7bc8a4bf7c426599765b1bd33217ec84023033672c1e9a8b35eaeaaaf8"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-win32.whl", hash = "sha256:12a2b561af122e3d94cdb97fe6fb2bb2b82cef0cdca131646fdb940a1eda04f0"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:3160a0fd9754aab7d47f95a6b63ab355388d890163eb03b2d2b87ab0a30cfa59"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:38e812a197bf8e71a59fe55b757a84c1f946d0ac114acafaafaf21667a7e169e"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6baf0baf0d5d265fa7944feb9f7451cc316bfe30e8df1a61b1bb08577c554f31"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8f25e17ab3039b05f762b0a55ae0b3632b2e073d9c8fc88e89aca31a6198e88f"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3747443b6a904001473370d7810aa19c3a180ccd52a7157aacc264a5ac79265e"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b116502087ce8a6b7a5f1814568ccbd0e9f6cfd99948aa59b0e241dc57cf739f"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d16fd5252f883eb074ca55cb622bc0bee49b979ae4e8639fff6ca3ff44f9f854"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21fa558996782fc226b529fdd2ed7866c2c6ec91cee82735c98a197fae39f706"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6f6c7a8a57e9405cad7485f4c9d3172ae486cfef1344b5ddd8e5239582d7355e"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ac3775e3311661d4adace3697a52ac0bab17edd166087d493b52d4f4f553f9f0"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:10c93628d7497c81686e8e5e557aafa78f230cd9e77dd0c40032ef90c18f2230"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:6f4f4668e1831850ebcc2fd0b1cd11721947b6dc7c00bf1c6bd3c929ae14f2c7"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:0be65ccf618c1e7ac9b849c315cc2e8a8751d9cfdaa43027d4f6624bd587ab7e"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:53d0a3fa5f8af98a1e261de6a3943ca631c526635eb5817a87a59d9a57ebf48f"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-win32.whl", hash = "sha256:a04f86f41a8916fe45ac5024ec477f41f886b3c435da2d4e3d2709b22ab02af1"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:830d2948a5ec37c386d3170c483063798d7879037492540f10a475e3fd6f244b"}, + {file = "charset_normalizer-3.1.0-py3-none-any.whl", hash = "sha256:3d9098b479e78c85080c98e1e35ff40b4a31d8953102bb0fd7d1b6f8a2111a3d"}, +] + +[[package]] +name = "click" +version = "8.1.3" +description = "Composable command line interface toolkit" +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"}, + {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} + +[[package]] +name = "colorama" +version = "0.4.6" +description = "Cross-platform colored terminal text." +category = "main" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +files = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] + +[[package]] +name = "dill" +version = "0.3.6" +description = "serialize all of python" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "dill-0.3.6-py3-none-any.whl", hash = "sha256:a07ffd2351b8c678dfc4a856a3005f8067aea51d6ba6c700796a4d9e280f39f0"}, + {file = "dill-0.3.6.tar.gz", hash = "sha256:e5db55f3687856d8fbdab002ed78544e1c4559a130302693d839dfe8f93f2373"}, +] + +[package.extras] +graph = ["objgraph (>=1.7.2)"] + +[[package]] +name = "idna" +version = "3.4" +description = "Internationalized Domain Names in Applications (IDNA)" +category = "main" +optional = false +python-versions = ">=3.5" +files = [ + {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, + {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, +] + +[[package]] +name = "isort" +version = "5.12.0" +description = "A Python utility / library to sort Python imports." +category = "dev" +optional = false +python-versions = ">=3.8.0" +files = [ + {file = "isort-5.12.0-py3-none-any.whl", hash = "sha256:f84c2818376e66cf843d497486ea8fed8700b340f308f076c6fb1229dff318b6"}, + {file = "isort-5.12.0.tar.gz", hash = "sha256:8bef7dde241278824a6d83f44a544709b065191b95b6e50894bdc722fcba0504"}, +] + +[package.extras] +colors = ["colorama (>=0.4.3)"] +pipfile-deprecated-finder = ["pip-shims (>=0.5.2)", "pipreqs", "requirementslib"] +plugins = ["setuptools"] +requirements-deprecated-finder = ["pip-api", "pipreqs"] + +[[package]] +name = "jsonschema" +version = "4.17.3" +description = "An implementation of JSON Schema validation for Python" +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "jsonschema-4.17.3-py3-none-any.whl", hash = "sha256:a870ad254da1a8ca84b6a2905cac29d265f805acc57af304784962a2aa6508f6"}, + {file = "jsonschema-4.17.3.tar.gz", hash = "sha256:0f864437ab8b6076ba6707453ef8f98a6a0d512a80e93f8abdb676f737ecb60d"}, +] + +[package.dependencies] +attrs = ">=17.4.0" +pyrsistent = ">=0.14.0,<0.17.0 || >0.17.0,<0.17.1 || >0.17.1,<0.17.2 || >0.17.2" + +[package.extras] +format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"] +format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "uri-template", "webcolors (>=1.11)"] + +[[package]] +name = "lazy-object-proxy" +version = "1.9.0" +description = "A fast and thorough lazy object proxy." +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "lazy-object-proxy-1.9.0.tar.gz", hash = "sha256:659fb5809fa4629b8a1ac5106f669cfc7bef26fbb389dda53b3e010d1ac4ebae"}, + {file = "lazy_object_proxy-1.9.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b40387277b0ed2d0602b8293b94d7257e17d1479e257b4de114ea11a8cb7f2d7"}, + {file = "lazy_object_proxy-1.9.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8c6cfb338b133fbdbc5cfaa10fe3c6aeea827db80c978dbd13bc9dd8526b7d4"}, + {file = "lazy_object_proxy-1.9.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:721532711daa7db0d8b779b0bb0318fa87af1c10d7fe5e52ef30f8eff254d0cd"}, + {file = "lazy_object_proxy-1.9.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:66a3de4a3ec06cd8af3f61b8e1ec67614fbb7c995d02fa224813cb7afefee701"}, + {file = "lazy_object_proxy-1.9.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:1aa3de4088c89a1b69f8ec0dcc169aa725b0ff017899ac568fe44ddc1396df46"}, + {file = "lazy_object_proxy-1.9.0-cp310-cp310-win32.whl", hash = "sha256:f0705c376533ed2a9e5e97aacdbfe04cecd71e0aa84c7c0595d02ef93b6e4455"}, + {file = "lazy_object_proxy-1.9.0-cp310-cp310-win_amd64.whl", hash = "sha256:ea806fd4c37bf7e7ad82537b0757999264d5f70c45468447bb2b91afdbe73a6e"}, + {file = "lazy_object_proxy-1.9.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:946d27deaff6cf8452ed0dba83ba38839a87f4f7a9732e8f9fd4107b21e6ff07"}, + {file = "lazy_object_proxy-1.9.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79a31b086e7e68b24b99b23d57723ef7e2c6d81ed21007b6281ebcd1688acb0a"}, + {file = "lazy_object_proxy-1.9.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f699ac1c768270c9e384e4cbd268d6e67aebcfae6cd623b4d7c3bfde5a35db59"}, + {file = "lazy_object_proxy-1.9.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bfb38f9ffb53b942f2b5954e0f610f1e721ccebe9cce9025a38c8ccf4a5183a4"}, + {file = "lazy_object_proxy-1.9.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:189bbd5d41ae7a498397287c408617fe5c48633e7755287b21d741f7db2706a9"}, + {file = "lazy_object_proxy-1.9.0-cp311-cp311-win32.whl", hash = "sha256:81fc4d08b062b535d95c9ea70dbe8a335c45c04029878e62d744bdced5141586"}, + {file = "lazy_object_proxy-1.9.0-cp311-cp311-win_amd64.whl", hash = "sha256:f2457189d8257dd41ae9b434ba33298aec198e30adf2dcdaaa3a28b9994f6adb"}, + {file = "lazy_object_proxy-1.9.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:d9e25ef10a39e8afe59a5c348a4dbf29b4868ab76269f81ce1674494e2565a6e"}, + {file = "lazy_object_proxy-1.9.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cbf9b082426036e19c6924a9ce90c740a9861e2bdc27a4834fd0a910742ac1e8"}, + {file = "lazy_object_proxy-1.9.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f5fa4a61ce2438267163891961cfd5e32ec97a2c444e5b842d574251ade27d2"}, + {file = "lazy_object_proxy-1.9.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:8fa02eaab317b1e9e03f69aab1f91e120e7899b392c4fc19807a8278a07a97e8"}, + {file = "lazy_object_proxy-1.9.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e7c21c95cae3c05c14aafffe2865bbd5e377cfc1348c4f7751d9dc9a48ca4bda"}, + {file = "lazy_object_proxy-1.9.0-cp37-cp37m-win32.whl", hash = "sha256:f12ad7126ae0c98d601a7ee504c1122bcef553d1d5e0c3bfa77b16b3968d2734"}, + {file = "lazy_object_proxy-1.9.0-cp37-cp37m-win_amd64.whl", hash = "sha256:edd20c5a55acb67c7ed471fa2b5fb66cb17f61430b7a6b9c3b4a1e40293b1671"}, + {file = "lazy_object_proxy-1.9.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2d0daa332786cf3bb49e10dc6a17a52f6a8f9601b4cf5c295a4f85854d61de63"}, + {file = "lazy_object_proxy-1.9.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cd077f3d04a58e83d04b20e334f678c2b0ff9879b9375ed107d5d07ff160171"}, + {file = "lazy_object_proxy-1.9.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:660c94ea760b3ce47d1855a30984c78327500493d396eac4dfd8bd82041b22be"}, + {file = "lazy_object_proxy-1.9.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:212774e4dfa851e74d393a2370871e174d7ff0ebc980907723bb67d25c8a7c30"}, + {file = "lazy_object_proxy-1.9.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:f0117049dd1d5635bbff65444496c90e0baa48ea405125c088e93d9cf4525b11"}, + {file = "lazy_object_proxy-1.9.0-cp38-cp38-win32.whl", hash = "sha256:0a891e4e41b54fd5b8313b96399f8b0e173bbbfc03c7631f01efbe29bb0bcf82"}, + {file = "lazy_object_proxy-1.9.0-cp38-cp38-win_amd64.whl", hash = "sha256:9990d8e71b9f6488e91ad25f322898c136b008d87bf852ff65391b004da5e17b"}, + {file = "lazy_object_proxy-1.9.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9e7551208b2aded9c1447453ee366f1c4070602b3d932ace044715d89666899b"}, + {file = "lazy_object_proxy-1.9.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f83ac4d83ef0ab017683d715ed356e30dd48a93746309c8f3517e1287523ef4"}, + {file = "lazy_object_proxy-1.9.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7322c3d6f1766d4ef1e51a465f47955f1e8123caee67dd641e67d539a534d006"}, + {file = "lazy_object_proxy-1.9.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:18b78ec83edbbeb69efdc0e9c1cb41a3b1b1ed11ddd8ded602464c3fc6020494"}, + {file = "lazy_object_proxy-1.9.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:09763491ce220c0299688940f8dc2c5d05fd1f45af1e42e636b2e8b2303e4382"}, + {file = "lazy_object_proxy-1.9.0-cp39-cp39-win32.whl", hash = "sha256:9090d8e53235aa280fc9239a86ae3ea8ac58eff66a705fa6aa2ec4968b95c821"}, + {file = "lazy_object_proxy-1.9.0-cp39-cp39-win_amd64.whl", hash = "sha256:db1c1722726f47e10e0b5fdbf15ac3b8adb58c091d12b3ab713965795036985f"}, +] + +[[package]] +name = "mccabe" +version = "0.7.0" +description = "McCabe checker, plugin for flake8" +category = "dev" +optional = false +python-versions = ">=3.6" +files = [ + {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, + {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, +] + +[[package]] +name = "mypy-extensions" +version = "1.0.0" +description = "Type system extensions for programs checked with the mypy type checker." +category = "dev" +optional = false +python-versions = ">=3.5" +files = [ + {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, + {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, +] + +[[package]] +name = "packaging" +version = "23.0" +description = "Core utilities for Python packages" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "packaging-23.0-py3-none-any.whl", hash = "sha256:714ac14496c3e68c99c29b00845f7a2b85f3bb6f1078fd9f72fd20f0570002b2"}, + {file = "packaging-23.0.tar.gz", hash = "sha256:b6ad297f8907de0fa2fe1ccbd26fdaf387f5f47c7275fedf8cce89f99446cf97"}, +] + +[[package]] +name = "pathspec" +version = "0.11.1" +description = "Utility library for gitignore style pattern matching of file paths." +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pathspec-0.11.1-py3-none-any.whl", hash = "sha256:d8af70af76652554bd134c22b3e8a1cc46ed7d91edcdd721ef1a0c51a84a5293"}, + {file = "pathspec-0.11.1.tar.gz", hash = "sha256:2798de800fa92780e33acca925945e9a19a133b715067cf165b8866c15a31687"}, +] + +[[package]] +name = "platformdirs" +version = "3.2.0" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "platformdirs-3.2.0-py3-none-any.whl", hash = "sha256:ebe11c0d7a805086e99506aa331612429a72ca7cd52a1f0d277dc4adc20cb10e"}, + {file = "platformdirs-3.2.0.tar.gz", hash = "sha256:d5b638ca397f25f979350ff789db335903d7ea010ab28903f57b27e1b16c2b08"}, +] + +[package.extras] +docs = ["furo (>=2022.12.7)", "proselint (>=0.13)", "sphinx (>=6.1.3)", "sphinx-autodoc-typehints (>=1.22,!=1.23.4)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.2.2)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"] + +[[package]] +name = "pylint" +version = "2.17.2" +description = "python code static checker" +category = "dev" +optional = false +python-versions = ">=3.7.2" +files = [ + {file = "pylint-2.17.2-py3-none-any.whl", hash = "sha256:001cc91366a7df2970941d7e6bbefcbf98694e00102c1f121c531a814ddc2ea8"}, + {file = "pylint-2.17.2.tar.gz", hash = "sha256:1b647da5249e7c279118f657ca28b6aaebb299f86bf92affc632acf199f7adbb"}, +] + +[package.dependencies] +astroid = ">=2.15.2,<=2.17.0-dev0" +colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} +dill = [ + {version = ">=0.2", markers = "python_version < \"3.11\""}, + {version = ">=0.3.6", markers = "python_version >= \"3.11\""}, +] +isort = ">=4.2.5,<6" +mccabe = ">=0.6,<0.8" +platformdirs = ">=2.2.0" +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} +tomlkit = ">=0.10.1" + +[package.extras] +spelling = ["pyenchant (>=3.2,<4.0)"] +testutils = ["gitpython (>3)"] + +[[package]] +name = "pyrsistent" +version = "0.19.3" +description = "Persistent/Functional/Immutable data structures" +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pyrsistent-0.19.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:20460ac0ea439a3e79caa1dbd560344b64ed75e85d8703943e0b66c2a6150e4a"}, + {file = "pyrsistent-0.19.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4c18264cb84b5e68e7085a43723f9e4c1fd1d935ab240ce02c0324a8e01ccb64"}, + {file = "pyrsistent-0.19.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4b774f9288dda8d425adb6544e5903f1fb6c273ab3128a355c6b972b7df39dcf"}, + {file = "pyrsistent-0.19.3-cp310-cp310-win32.whl", hash = "sha256:5a474fb80f5e0d6c9394d8db0fc19e90fa540b82ee52dba7d246a7791712f74a"}, + {file = "pyrsistent-0.19.3-cp310-cp310-win_amd64.whl", hash = "sha256:49c32f216c17148695ca0e02a5c521e28a4ee6c5089f97e34fe24163113722da"}, + {file = "pyrsistent-0.19.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f0774bf48631f3a20471dd7c5989657b639fd2d285b861237ea9e82c36a415a9"}, + {file = "pyrsistent-0.19.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3ab2204234c0ecd8b9368dbd6a53e83c3d4f3cab10ecaf6d0e772f456c442393"}, + {file = "pyrsistent-0.19.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e42296a09e83028b3476f7073fcb69ffebac0e66dbbfd1bd847d61f74db30f19"}, + {file = "pyrsistent-0.19.3-cp311-cp311-win32.whl", hash = "sha256:64220c429e42a7150f4bfd280f6f4bb2850f95956bde93c6fda1b70507af6ef3"}, + {file = "pyrsistent-0.19.3-cp311-cp311-win_amd64.whl", hash = "sha256:016ad1afadf318eb7911baa24b049909f7f3bb2c5b1ed7b6a8f21db21ea3faa8"}, + {file = "pyrsistent-0.19.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c4db1bd596fefd66b296a3d5d943c94f4fac5bcd13e99bffe2ba6a759d959a28"}, + {file = "pyrsistent-0.19.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aeda827381f5e5d65cced3024126529ddc4289d944f75e090572c77ceb19adbf"}, + {file = "pyrsistent-0.19.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:42ac0b2f44607eb92ae88609eda931a4f0dfa03038c44c772e07f43e738bcac9"}, + {file = "pyrsistent-0.19.3-cp37-cp37m-win32.whl", hash = "sha256:e8f2b814a3dc6225964fa03d8582c6e0b6650d68a232df41e3cc1b66a5d2f8d1"}, + {file = "pyrsistent-0.19.3-cp37-cp37m-win_amd64.whl", hash = "sha256:c9bb60a40a0ab9aba40a59f68214eed5a29c6274c83b2cc206a359c4a89fa41b"}, + {file = "pyrsistent-0.19.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:a2471f3f8693101975b1ff85ffd19bb7ca7dd7c38f8a81701f67d6b4f97b87d8"}, + {file = "pyrsistent-0.19.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc5d149f31706762c1f8bda2e8c4f8fead6e80312e3692619a75301d3dbb819a"}, + {file = "pyrsistent-0.19.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3311cb4237a341aa52ab8448c27e3a9931e2ee09561ad150ba94e4cfd3fc888c"}, + {file = "pyrsistent-0.19.3-cp38-cp38-win32.whl", hash = "sha256:f0e7c4b2f77593871e918be000b96c8107da48444d57005b6a6bc61fb4331b2c"}, + {file = "pyrsistent-0.19.3-cp38-cp38-win_amd64.whl", hash = "sha256:c147257a92374fde8498491f53ffa8f4822cd70c0d85037e09028e478cababb7"}, + {file = "pyrsistent-0.19.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:b735e538f74ec31378f5a1e3886a26d2ca6351106b4dfde376a26fc32a044edc"}, + {file = "pyrsistent-0.19.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99abb85579e2165bd8522f0c0138864da97847875ecbd45f3e7e2af569bfc6f2"}, + {file = "pyrsistent-0.19.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3a8cb235fa6d3fd7aae6a4f1429bbb1fec1577d978098da1252f0489937786f3"}, + {file = "pyrsistent-0.19.3-cp39-cp39-win32.whl", hash = "sha256:c74bed51f9b41c48366a286395c67f4e894374306b197e62810e0fdaf2364da2"}, + {file = "pyrsistent-0.19.3-cp39-cp39-win_amd64.whl", hash = "sha256:878433581fc23e906d947a6814336eee031a00e6defba224234169ae3d3d6a98"}, + {file = "pyrsistent-0.19.3-py3-none-any.whl", hash = "sha256:ccf0d6bd208f8111179f0c26fdf84ed7c3891982f2edaeae7422575f47e66b64"}, + {file = "pyrsistent-0.19.3.tar.gz", hash = "sha256:1a2994773706bbb4995c31a97bc94f1418314923bd1048c6d964837040376440"}, +] + +[[package]] +name = "requests" +version = "2.28.2" +description = "Python HTTP for Humans." +category = "main" +optional = false +python-versions = ">=3.7, <4" +files = [ + {file = "requests-2.28.2-py3-none-any.whl", hash = "sha256:64299f4909223da747622c030b781c0d7811e359c37124b4bd368fb8c6518baa"}, + {file = "requests-2.28.2.tar.gz", hash = "sha256:98b1b2782e3c6c4904938b84c0eb932721069dfdb9134313beff7c83c2df24bf"}, +] + +[package.dependencies] +certifi = ">=2017.4.17" +charset-normalizer = ">=2,<4" +idna = ">=2.5,<4" +urllib3 = ">=1.21.1,<1.27" + +[package.extras] +socks = ["PySocks (>=1.5.6,!=1.5.7)"] +use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] + +[[package]] +name = "returns" +version = "0.19.0" +description = "Make your functions return something meaningful, typed, and safe!" +category = "main" +optional = false +python-versions = ">=3.7,<4.0" +files = [ + {file = "returns-0.19.0-py3-none-any.whl", hash = "sha256:ae3ce9e5165d1218905291b4d5881b4e8a86ca478437bef3b0af1de8df57ec69"}, + {file = "returns-0.19.0.tar.gz", hash = "sha256:4544bb67849c1ef1bbf7823759d433a773959e5b77a8fd06d01fef6d060f2ac5"}, +] + +[package.dependencies] +typing-extensions = ">=4.0,<5.0" + +[[package]] +name = "termcolor" +version = "2.2.0" +description = "ANSI color formatting for output in terminal" +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "termcolor-2.2.0-py3-none-any.whl", hash = "sha256:91ddd848e7251200eac969846cbae2dacd7d71c2871e92733289e7e3666f48e7"}, + {file = "termcolor-2.2.0.tar.gz", hash = "sha256:dfc8ac3f350788f23b2947b3e6cfa5a53b630b612e6cd8965a015a776020b99a"}, +] + +[package.extras] +tests = ["pytest", "pytest-cov"] + +[[package]] +name = "tomli" +version = "2.0.1" +description = "A lil' TOML parser" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, + {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, +] + +[[package]] +name = "tomlkit" +version = "0.11.7" +description = "Style preserving TOML library" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "tomlkit-0.11.7-py3-none-any.whl", hash = "sha256:5325463a7da2ef0c6bbfefb62a3dc883aebe679984709aee32a317907d0a8d3c"}, + {file = "tomlkit-0.11.7.tar.gz", hash = "sha256:f392ef70ad87a672f02519f99967d28a4d3047133e2d1df936511465fbb3791d"}, +] + +[[package]] +name = "typing-extensions" +version = "4.5.0" +description = "Backported and Experimental Type Hints for Python 3.7+" +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "typing_extensions-4.5.0-py3-none-any.whl", hash = "sha256:fb33085c39dd998ac16d1431ebc293a8b3eedd00fd4a32de0ff79002c19511b4"}, + {file = "typing_extensions-4.5.0.tar.gz", hash = "sha256:5cb5f4a79139d699607b3ef622a1dedafa84e115ab0024e0d9c044a9479ca7cb"}, +] + +[[package]] +name = "urllib3" +version = "1.26.15" +description = "HTTP library with thread-safe connection pooling, file post, and more." +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" +files = [ + {file = "urllib3-1.26.15-py2.py3-none-any.whl", hash = "sha256:aa751d169e23c7479ce47a0cb0da579e3ede798f994f5816a74e4f4500dcea42"}, + {file = "urllib3-1.26.15.tar.gz", hash = "sha256:8a388717b9476f934a21484e8c8e61875ab60644d29b9b39e11e4b9dc1c6b305"}, +] + +[package.extras] +brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"] +secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"] +socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] + +[[package]] +name = "wrapt" +version = "1.15.0" +description = "Module for decorators, wrappers and monkey patching." +category = "dev" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" +files = [ + {file = "wrapt-1.15.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:ca1cccf838cd28d5a0883b342474c630ac48cac5df0ee6eacc9c7290f76b11c1"}, + {file = "wrapt-1.15.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:e826aadda3cae59295b95343db8f3d965fb31059da7de01ee8d1c40a60398b29"}, + {file = "wrapt-1.15.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:5fc8e02f5984a55d2c653f5fea93531e9836abbd84342c1d1e17abc4a15084c2"}, + {file = "wrapt-1.15.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:96e25c8603a155559231c19c0349245eeb4ac0096fe3c1d0be5c47e075bd4f46"}, + {file = "wrapt-1.15.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:40737a081d7497efea35ab9304b829b857f21558acfc7b3272f908d33b0d9d4c"}, + {file = "wrapt-1.15.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:f87ec75864c37c4c6cb908d282e1969e79763e0d9becdfe9fe5473b7bb1e5f09"}, + {file = "wrapt-1.15.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:1286eb30261894e4c70d124d44b7fd07825340869945c79d05bda53a40caa079"}, + {file = "wrapt-1.15.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:493d389a2b63c88ad56cdc35d0fa5752daac56ca755805b1b0c530f785767d5e"}, + {file = "wrapt-1.15.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:58d7a75d731e8c63614222bcb21dd992b4ab01a399f1f09dd82af17bbfc2368a"}, + {file = "wrapt-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:21f6d9a0d5b3a207cdf7acf8e58d7d13d463e639f0c7e01d82cdb671e6cb7923"}, + {file = "wrapt-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ce42618f67741d4697684e501ef02f29e758a123aa2d669e2d964ff734ee00ee"}, + {file = "wrapt-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41d07d029dd4157ae27beab04d22b8e261eddfc6ecd64ff7000b10dc8b3a5727"}, + {file = "wrapt-1.15.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54accd4b8bc202966bafafd16e69da9d5640ff92389d33d28555c5fd4f25ccb7"}, + {file = "wrapt-1.15.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2fbfbca668dd15b744418265a9607baa970c347eefd0db6a518aaf0cfbd153c0"}, + {file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:76e9c727a874b4856d11a32fb0b389afc61ce8aaf281ada613713ddeadd1cfec"}, + {file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e20076a211cd6f9b44a6be58f7eeafa7ab5720eb796975d0c03f05b47d89eb90"}, + {file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a74d56552ddbde46c246b5b89199cb3fd182f9c346c784e1a93e4dc3f5ec9975"}, + {file = "wrapt-1.15.0-cp310-cp310-win32.whl", hash = "sha256:26458da5653aa5b3d8dc8b24192f574a58984c749401f98fff994d41d3f08da1"}, + {file = "wrapt-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:75760a47c06b5974aa5e01949bf7e66d2af4d08cb8c1d6516af5e39595397f5e"}, + {file = "wrapt-1.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ba1711cda2d30634a7e452fc79eabcadaffedf241ff206db2ee93dd2c89a60e7"}, + {file = "wrapt-1.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:56374914b132c702aa9aa9959c550004b8847148f95e1b824772d453ac204a72"}, + {file = "wrapt-1.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a89ce3fd220ff144bd9d54da333ec0de0399b52c9ac3d2ce34b569cf1a5748fb"}, + {file = "wrapt-1.15.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3bbe623731d03b186b3d6b0d6f51865bf598587c38d6f7b0be2e27414f7f214e"}, + {file = "wrapt-1.15.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3abbe948c3cbde2689370a262a8d04e32ec2dd4f27103669a45c6929bcdbfe7c"}, + {file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b67b819628e3b748fd3c2192c15fb951f549d0f47c0449af0764d7647302fda3"}, + {file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7eebcdbe3677e58dd4c0e03b4f2cfa346ed4049687d839adad68cc38bb559c92"}, + {file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:74934ebd71950e3db69960a7da29204f89624dde411afbfb3b4858c1409b1e98"}, + {file = "wrapt-1.15.0-cp311-cp311-win32.whl", hash = "sha256:bd84395aab8e4d36263cd1b9308cd504f6cf713b7d6d3ce25ea55670baec5416"}, + {file = "wrapt-1.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:a487f72a25904e2b4bbc0817ce7a8de94363bd7e79890510174da9d901c38705"}, + {file = "wrapt-1.15.0-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:4ff0d20f2e670800d3ed2b220d40984162089a6e2c9646fdb09b85e6f9a8fc29"}, + {file = "wrapt-1.15.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:9ed6aa0726b9b60911f4aed8ec5b8dd7bf3491476015819f56473ffaef8959bd"}, + {file = "wrapt-1.15.0-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:896689fddba4f23ef7c718279e42f8834041a21342d95e56922e1c10c0cc7afb"}, + {file = "wrapt-1.15.0-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:75669d77bb2c071333417617a235324a1618dba66f82a750362eccbe5b61d248"}, + {file = "wrapt-1.15.0-cp35-cp35m-win32.whl", hash = "sha256:fbec11614dba0424ca72f4e8ba3c420dba07b4a7c206c8c8e4e73f2e98f4c559"}, + {file = "wrapt-1.15.0-cp35-cp35m-win_amd64.whl", hash = "sha256:fd69666217b62fa5d7c6aa88e507493a34dec4fa20c5bd925e4bc12fce586639"}, + {file = "wrapt-1.15.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:b0724f05c396b0a4c36a3226c31648385deb6a65d8992644c12a4963c70326ba"}, + {file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bbeccb1aa40ab88cd29e6c7d8585582c99548f55f9b2581dfc5ba68c59a85752"}, + {file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:38adf7198f8f154502883242f9fe7333ab05a5b02de7d83aa2d88ea621f13364"}, + {file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:578383d740457fa790fdf85e6d346fda1416a40549fe8db08e5e9bd281c6a475"}, + {file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:a4cbb9ff5795cd66f0066bdf5947f170f5d63a9274f99bdbca02fd973adcf2a8"}, + {file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:af5bd9ccb188f6a5fdda9f1f09d9f4c86cc8a539bd48a0bfdc97723970348418"}, + {file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:b56d5519e470d3f2fe4aa7585f0632b060d532d0696c5bdfb5e8319e1d0f69a2"}, + {file = "wrapt-1.15.0-cp36-cp36m-win32.whl", hash = "sha256:77d4c1b881076c3ba173484dfa53d3582c1c8ff1f914c6461ab70c8428b796c1"}, + {file = "wrapt-1.15.0-cp36-cp36m-win_amd64.whl", hash = "sha256:077ff0d1f9d9e4ce6476c1a924a3332452c1406e59d90a2cf24aeb29eeac9420"}, + {file = "wrapt-1.15.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5c5aa28df055697d7c37d2099a7bc09f559d5053c3349b1ad0c39000e611d317"}, + {file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3a8564f283394634a7a7054b7983e47dbf39c07712d7b177b37e03f2467a024e"}, + {file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:780c82a41dc493b62fc5884fb1d3a3b81106642c5c5c78d6a0d4cbe96d62ba7e"}, + {file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e169e957c33576f47e21864cf3fc9ff47c223a4ebca8960079b8bd36cb014fd0"}, + {file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b02f21c1e2074943312d03d243ac4388319f2456576b2c6023041c4d57cd7019"}, + {file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f2e69b3ed24544b0d3dbe2c5c0ba5153ce50dcebb576fdc4696d52aa22db6034"}, + {file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d787272ed958a05b2c86311d3a4135d3c2aeea4fc655705f074130aa57d71653"}, + {file = "wrapt-1.15.0-cp37-cp37m-win32.whl", hash = "sha256:02fce1852f755f44f95af51f69d22e45080102e9d00258053b79367d07af39c0"}, + {file = "wrapt-1.15.0-cp37-cp37m-win_amd64.whl", hash = "sha256:abd52a09d03adf9c763d706df707c343293d5d106aea53483e0ec8d9e310ad5e"}, + {file = "wrapt-1.15.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cdb4f085756c96a3af04e6eca7f08b1345e94b53af8921b25c72f096e704e145"}, + {file = "wrapt-1.15.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:230ae493696a371f1dbffaad3dafbb742a4d27a0afd2b1aecebe52b740167e7f"}, + {file = "wrapt-1.15.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63424c681923b9f3bfbc5e3205aafe790904053d42ddcc08542181a30a7a51bd"}, + {file = "wrapt-1.15.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6bcbfc99f55655c3d93feb7ef3800bd5bbe963a755687cbf1f490a71fb7794b"}, + {file = "wrapt-1.15.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c99f4309f5145b93eca6e35ac1a988f0dc0a7ccf9ccdcd78d3c0adf57224e62f"}, + {file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b130fe77361d6771ecf5a219d8e0817d61b236b7d8b37cc045172e574ed219e6"}, + {file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:96177eb5645b1c6985f5c11d03fc2dbda9ad24ec0f3a46dcce91445747e15094"}, + {file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d5fe3e099cf07d0fb5a1e23d399e5d4d1ca3e6dfcbe5c8570ccff3e9208274f7"}, + {file = "wrapt-1.15.0-cp38-cp38-win32.whl", hash = "sha256:abd8f36c99512755b8456047b7be10372fca271bf1467a1caa88db991e7c421b"}, + {file = "wrapt-1.15.0-cp38-cp38-win_amd64.whl", hash = "sha256:b06fa97478a5f478fb05e1980980a7cdf2712015493b44d0c87606c1513ed5b1"}, + {file = "wrapt-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2e51de54d4fb8fb50d6ee8327f9828306a959ae394d3e01a1ba8b2f937747d86"}, + {file = "wrapt-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0970ddb69bba00670e58955f8019bec4a42d1785db3faa043c33d81de2bf843c"}, + {file = "wrapt-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76407ab327158c510f44ded207e2f76b657303e17cb7a572ffe2f5a8a48aa04d"}, + {file = "wrapt-1.15.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cd525e0e52a5ff16653a3fc9e3dd827981917d34996600bbc34c05d048ca35cc"}, + {file = "wrapt-1.15.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d37ac69edc5614b90516807de32d08cb8e7b12260a285ee330955604ed9dd29"}, + {file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:078e2a1a86544e644a68422f881c48b84fef6d18f8c7a957ffd3f2e0a74a0d4a"}, + {file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:2cf56d0e237280baed46f0b5316661da892565ff58309d4d2ed7dba763d984b8"}, + {file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7dc0713bf81287a00516ef43137273b23ee414fe41a3c14be10dd95ed98a2df9"}, + {file = "wrapt-1.15.0-cp39-cp39-win32.whl", hash = "sha256:46ed616d5fb42f98630ed70c3529541408166c22cdfd4540b88d5f21006b0eff"}, + {file = "wrapt-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:eef4d64c650f33347c1f9266fa5ae001440b232ad9b98f1f43dfe7a79435c0a6"}, + {file = "wrapt-1.15.0-py3-none-any.whl", hash = "sha256:64b1df0f83706b4ef4cfb4fb0e4c2669100fd7ecacfb59e091fad300d4e04640"}, + {file = "wrapt-1.15.0.tar.gz", hash = "sha256:d06730c6aed78cee4126234cf2d071e01b44b915e725a6cb439a879ec9754a3a"}, +] + +[metadata] +lock-version = "2.0" +python-versions = "^3.10" +content-hash = "abdfc665273077e72886ea627e7bcb2286e269d94b983741b1987f42614281f2" diff --git a/scripts/integrations-cli/pyproject.toml b/scripts/integrations-cli/pyproject.toml index 3403f6ad7..41500ca6e 100644 --- a/scripts/integrations-cli/pyproject.toml +++ b/scripts/integrations-cli/pyproject.toml @@ -22,6 +22,7 @@ click = "^8.1.3" returns = "^0.19.0" termcolor = "^2.2.0" jsonschema = "^4.17.3" +requests = "^2.28.2" [tool.poetry.dev-dependencies] black = "^23.3.0" diff --git a/scripts/integrations-cli/template-dashboards/http.ndjson b/scripts/integrations-cli/template-dashboards/http.ndjson new file mode 100644 index 000000000..71baa411c --- /dev/null +++ b/scripts/integrations-cli/template-dashboards/http.ndjson @@ -0,0 +1,10 @@ +{"attributes":{"fields":"[{\"count\":0,\"name\":\"@timestamp\",\"type\":\"date\",\"esTypes\":[\"date\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"_id\",\"type\":\"string\",\"esTypes\":[\"_id\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"count\":0,\"name\":\"_index\",\"type\":\"string\",\"esTypes\":[\"_index\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"count\":0,\"name\":\"_score\",\"type\":\"number\",\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"_source\",\"type\":\"_source\",\"esTypes\":[\"_source\"],\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"_type\",\"type\":\"string\",\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"attributes.data_stream.dataset\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"attributes.data_stream.dataset.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"attributes.data_stream.dataset\"}}},{\"count\":0,\"name\":\"attributes.data_stream.namespace\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"attributes.data_stream.namespace.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"attributes.data_stream.namespace\"}}},{\"count\":0,\"name\":\"attributes.data_stream.type\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"attributes.data_stream.type.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"attributes.data_stream.type\"}}},{\"count\":0,\"name\":\"body\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"body.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"body\"}}},{\"count\":0,\"name\":\"communication.source.address\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"communication.source.address.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"communication.source.address\"}}},{\"count\":0,\"name\":\"communication.source.ip\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"communication.source.ip.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"communication.source.ip\"}}},{\"count\":0,\"name\":\"event.category\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"event.category.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"event.category\"}}},{\"count\":0,\"name\":\"event.domain\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"event.domain.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"event.domain\"}}},{\"count\":0,\"name\":\"event.kind\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"event.kind.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"event.kind\"}}},{\"count\":0,\"name\":\"event.name\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"event.name.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"event.name\"}}},{\"count\":0,\"name\":\"event.result\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"event.result.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"event.result\"}}},{\"count\":0,\"name\":\"event.type\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"event.type.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"event.type\"}}},{\"count\":0,\"name\":\"http.flavor\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"http.flavor.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"http.flavor\"}}},{\"count\":0,\"name\":\"http.request.method\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"http.request.method.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"http.request.method\"}}},{\"count\":0,\"name\":\"http.response.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"http.response.status_code\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"http.response.status_code.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"http.response.status_code\"}}},{\"count\":0,\"name\":\"http.url\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"http.url\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"http.url\"}}},{\"count\":0,\"name\":\"observerTime\",\"type\":\"date\",\"esTypes\":[\"date\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"span_id\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"span_id.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"span_id\"}}},{\"count\":0,\"name\":\"trace_id\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"trace_id.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"trace_id\"}}}]","timeFieldName":"@timestamp","title":"sso_logs-*-*"},"id":"47892350-b495-11ed-af0a-cf5c93b5a3b6","migrationVersion":{"index-pattern":"7.6.0"},"references":[],"type":"index-pattern","updated_at":"2023-02-26T00:34:36.592Z","version":"WzYxLDdd"} +{"attributes":{"columns":["http.request.method","http.response.status_code"],"description":"","hits":0,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\n \"highlightAll\": true,\n \"version\": true,\n \"query\": {\n \"query\": \"event.domain:nginx.access\",\n \"language\": \"kuery\"\n },\n \"filter\": [],\n \"indexRefName\": \"kibanaSavedObjectMeta.searchSourceJSON.index\"\n}"},"sort":[],"title":"[NGINX Core Logs 1.0] Nginx Access Logs","version":1},"id":"d80e05b2-518c-4c3d-9651-4c9d8632dce4","migrationVersion":{"search":"7.9.3"},"references":[{"id":"47892350-b495-11ed-af0a-cf5c93b5a3b6","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"type":"search","updated_at":"2023-02-26T00:34:36.592Z","version":"WzYyLDdd"} +{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[]}"},"savedSearchRefName":"search_0","title":"[NGINX Core Logs 1.0] Response codes over time","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"[NGINX Core Logs 1.0] Response codes over time\",\"type\":\"histogram\",\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"params\":{},\"schema\":\"metric\"},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"params\":{\"field\":\"@timestamp\",\"timeRange\":{\"from\":\"now-24h\",\"to\":\"now\"},\"useNormalizedOpenSearchInterval\":true,\"scaleMetricValues\":false,\"interval\":\"auto\",\"drop_partials\":false,\"min_doc_count\":1,\"extended_bounds\":{}},\"schema\":\"segment\"},{\"id\":\"3\",\"enabled\":true,\"type\":\"filters\",\"params\":{\"filters\":[{\"input\":{\"query\":\"http.response.status_code:[200 TO 299]\",\"language\":\"lucene\"},\"label\":\"200s\"},{\"input\":{\"query\":\"http.response.status_code:[300 TO 399]\",\"language\":\"lucene\"},\"label\":\"300s\"},{\"input\":{\"query\":\"http.response.status_code:[400 TO 499]\",\"language\":\"lucene\"},\"label\":\"400s\"},{\"input\":{\"query\":\"http.response.status_code:[500 TO 599]\",\"language\":\"lucene\"},\"label\":\"500s\"},{\"input\":{\"query\":\"http.response.status_code:0\",\"language\":\"lucene\"},\"label\":\"0\"}]},\"schema\":\"group\"}],\"params\":{\"type\":\"histogram\",\"grid\":{\"categoryLines\":false},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"filter\":true,\"truncate\":100},\"title\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Count\"}}],\"seriesParams\":[{\"show\":true,\"type\":\"histogram\",\"mode\":\"stacked\",\"data\":{\"label\":\"Count\",\"id\":\"1\"},\"valueAxis\":\"ValueAxis-1\",\"drawLinesBetweenPoints\":true,\"lineWidth\":2,\"showCircles\":true}],\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"times\":[],\"addTimeMarker\":false,\"labels\":{\"show\":false},\"thresholdLine\":{\"show\":false,\"value\":10,\"width\":1,\"style\":\"full\",\"color\":\"#E7664C\"}}}"},"id":"3b49a65d-54d8-483d-a8f0-3d7c855e1ecf","migrationVersion":{"visualization":"7.10.0"},"references":[{"id":"d80e05b2-518c-4c3d-9651-4c9d8632dce4","name":"search_0","type":"search"}],"type":"visualization","updated_at":"2023-02-26T00:34:36.592Z","version":"WzYzLDdd"} +{"attributes":{"columns":["_source"],"description":"","hits":0,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\n \"highlightAll\": true,\n \"query\": {\n \"query\": \"http.response.status_code >= 300 and event.domain:nginx.access\",\n \"language\": \"kuery\"\n },\n \"version\": true,\n \"highlight\": {\n \"post_tags\": [\n \"@/kibana-highlighted-field@\"\n ],\n \"fields\": {\n \"*\": {}\n },\n \"pre_tags\": [\n \"@kibana-highlighted-field@\"\n ],\n \"require_field_match\": false,\n \"fragment_size\": 2147483647\n },\n \"filter\": [],\n \"indexRefName\": \"kibanaSavedObjectMeta.searchSourceJSON.index\"\n}"},"sort":[["@timestamp","desc"]],"title":"[NGINX Core Logs 1.0] Nginx Error Logs","version":1},"id":"9f820fbe-ddde-43a2-9402-30bd295c97f6","migrationVersion":{"search":"7.9.3"},"references":[{"id":"47892350-b495-11ed-af0a-cf5c93b5a3b6","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"type":"search","updated_at":"2023-02-26T00:34:36.592Z","version":"WzY0LDdd"} +{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[]}"},"savedSearchRefName":"search_0","title":"[NGINX Core Logs 1.0] Errors over time","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"[NGINX Core Logs 1.0] Errors over time\",\"type\":\"histogram\",\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"params\":{},\"schema\":\"metric\"},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"params\":{\"field\":\"@timestamp\",\"timeRange\":{\"from\":\"now-24h\",\"to\":\"now\"},\"useNormalizedOpenSearchInterval\":true,\"scaleMetricValues\":false,\"interval\":\"auto\",\"drop_partials\":false,\"min_doc_count\":1,\"extended_bounds\":{}},\"schema\":\"segment\"}],\"params\":{\"type\":\"histogram\",\"grid\":{\"categoryLines\":false},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"filter\":true,\"truncate\":100},\"title\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Count\"}}],\"seriesParams\":[{\"show\":true,\"type\":\"histogram\",\"mode\":\"stacked\",\"data\":{\"label\":\"Count\",\"id\":\"1\"},\"valueAxis\":\"ValueAxis-1\",\"drawLinesBetweenPoints\":true,\"lineWidth\":2,\"showCircles\":true}],\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"times\":[],\"addTimeMarker\":false,\"labels\":{\"show\":false},\"thresholdLine\":{\"show\":false,\"value\":10,\"width\":1,\"style\":\"full\",\"color\":\"#E7664C\"}}}"},"id":"865e577b-634b-4a65-b9d6-7e324c395d18","migrationVersion":{"visualization":"7.10.0"},"references":[{"id":"9f820fbe-ddde-43a2-9402-30bd295c97f6","name":"search_0","type":"search"}],"type":"visualization","updated_at":"2023-02-26T00:34:36.592Z","version":"WzY1LDdd"} +{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}"},"savedSearchRefName":"search_0","title":"Top Paths","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"Top Paths\",\"type\":\"table\",\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"params\":{},\"schema\":\"metric\"},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"params\":{\"field\":\"http.url\",\"orderBy\":\"1\",\"order\":\"desc\",\"size\":10,\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\",\"customLabel\":\"Paths\"},\"schema\":\"bucket\"}],\"params\":{\"perPage\":10,\"showPartialRows\":false,\"showMetricsAtAllLevels\":false,\"showTotal\":false,\"totalFunc\":\"sum\",\"percentageCol\":\"\"}}"},"id":"dc1803f0-b478-11ed-9063-ebe46f9ac203","migrationVersion":{"visualization":"7.10.0"},"references":[{"id":"d80e05b2-518c-4c3d-9651-4c9d8632dce4","name":"search_0","type":"search"}],"type":"visualization","updated_at":"2023-02-26T00:34:36.592Z","version":"WzY2LDdd"} +{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}"},"savedSearchRefName":"search_0","title":"Data Volume","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"Data Volume\",\"type\":\"area\",\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"sum\",\"params\":{\"field\":\"http.response.bytes\",\"customLabel\":\"Response Bytes\"},\"schema\":\"metric\"},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"params\":{\"field\":\"observerTime\",\"timeRange\":{\"from\":\"now-15m\",\"to\":\"now\"},\"useNormalizedOpenSearchInterval\":true,\"scaleMetricValues\":false,\"interval\":\"auto\",\"drop_partials\":false,\"min_doc_count\":1,\"extended_bounds\":{},\"customLabel\":\"\"},\"schema\":\"segment\"}],\"params\":{\"type\":\"area\",\"grid\":{\"categoryLines\":false},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"filter\":true,\"truncate\":100},\"title\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Response Bytes\"}}],\"seriesParams\":[{\"show\":true,\"type\":\"area\",\"mode\":\"stacked\",\"data\":{\"label\":\"Response Bytes\",\"id\":\"1\"},\"drawLinesBetweenPoints\":true,\"lineWidth\":2,\"showCircles\":true,\"interpolate\":\"linear\",\"valueAxis\":\"ValueAxis-1\"}],\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"times\":[],\"addTimeMarker\":false,\"thresholdLine\":{\"show\":false,\"value\":10,\"width\":1,\"style\":\"full\",\"color\":\"#E7664C\"},\"labels\":{}}}"},"id":"99acc580-b47a-11ed-9063-ebe46f9ac203","migrationVersion":{"visualization":"7.10.0"},"references":[{"id":"d80e05b2-518c-4c3d-9651-4c9d8632dce4","name":"search_0","type":"search"}],"type":"visualization","updated_at":"2023-02-26T00:34:36.592Z","version":"WzY3LDdd"} +{"attributes":{"description":"requests per minute aggregation","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"title":"Req-per-min","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"Req-per-min\",\"type\":\"table\",\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"moving_avg\",\"params\":{\"metricAgg\":\"custom\",\"customMetric\":{\"id\":\"1-metric\",\"enabled\":true,\"type\":\"count\",\"params\":{}},\"window\":5,\"script\":\"MovingFunctions.unweightedAvg(values)\"},\"schema\":\"metric\"},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"params\":{\"field\":\"@timestamp\",\"timeRange\":{\"from\":\"2023-02-24T17:25:00.000Z\",\"to\":\"2023-02-24T17:30:00.000Z\"},\"useNormalizedOpenSearchInterval\":true,\"scaleMetricValues\":false,\"interval\":\"m\",\"drop_partials\":false,\"min_doc_count\":0,\"extended_bounds\":{},\"customLabel\":\"Req/Min\"},\"schema\":\"bucket\"}],\"params\":{\"perPage\":10,\"showPartialRows\":false,\"showMetricsAtAllLevels\":false,\"showTotal\":false,\"totalFunc\":\"sum\",\"percentageCol\":\"\"}}"},"id":"01ea64d0-b62f-11ed-a677-43d7aa86763b","migrationVersion":{"visualization":"7.10.0"},"references":[{"id":"47892350-b495-11ed-af0a-cf5c93b5a3b6","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"type":"visualization","updated_at":"2023-02-26T23:40:53.020Z","version":"WzcyLDdd"} +{"attributes":{"description":"Nginx dashboard with basic Observability on access / error logs","hits":0,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[]}"},"optionsJSON":"{\"hidePanelTitles\":false,\"useMargins\":true}","panelsJSON":"[{\"version\":\"2.5.0\",\"gridData\":{\"h\":8,\"i\":\"1f31e50b-06e3-41e6-972e-e4e5fe1a9872\",\"w\":48,\"x\":0,\"y\":0},\"panelIndex\":\"1f31e50b-06e3-41e6-972e-e4e5fe1a9872\",\"embeddableConfig\":{},\"panelRefName\":\"panel_0\"},{\"version\":\"2.5.0\",\"gridData\":{\"h\":9,\"i\":\"d91a8da4-b34b-470a-aca6-9c76b47cd6fb\",\"w\":24,\"x\":0,\"y\":8},\"panelIndex\":\"d91a8da4-b34b-470a-aca6-9c76b47cd6fb\",\"embeddableConfig\":{},\"panelRefName\":\"panel_1\"},{\"version\":\"2.5.0\",\"gridData\":{\"h\":15,\"i\":\"27149e5a-3a77-4f3c-800e-8a160c3765f4\",\"w\":24,\"x\":24,\"y\":8},\"panelIndex\":\"27149e5a-3a77-4f3c-800e-8a160c3765f4\",\"embeddableConfig\":{},\"panelRefName\":\"panel_2\"},{\"version\":\"2.5.0\",\"gridData\":{\"x\":0,\"y\":17,\"w\":24,\"h\":15,\"i\":\"4d8c2aa7-159c-4a1a-80ff-00a9299056ce\"},\"panelIndex\":\"4d8c2aa7-159c-4a1a-80ff-00a9299056ce\",\"embeddableConfig\":{},\"panelRefName\":\"panel_3\"},{\"version\":\"2.5.0\",\"gridData\":{\"x\":24,\"y\":23,\"w\":24,\"h\":15,\"i\":\"800b7f19-f50c-417f-8987-21b930531cbe\"},\"panelIndex\":\"800b7f19-f50c-417f-8987-21b930531cbe\",\"embeddableConfig\":{},\"panelRefName\":\"panel_4\"}]","timeRestore":false,"title":"[NGINX Core Logs 1.0] Overview","version":1},"id":"96847220-5261-44d0-89b4-65f3a659f13a","migrationVersion":{"dashboard":"7.9.3"},"references":[{"id":"3b49a65d-54d8-483d-a8f0-3d7c855e1ecf","name":"panel_0","type":"visualization"},{"id":"865e577b-634b-4a65-b9d6-7e324c395d18","name":"panel_1","type":"visualization"},{"id":"dc1803f0-b478-11ed-9063-ebe46f9ac203","name":"panel_2","type":"visualization"},{"id":"99acc580-b47a-11ed-9063-ebe46f9ac203","name":"panel_3","type":"visualization"},{"id":"01ea64d0-b62f-11ed-a677-43d7aa86763b","name":"panel_4","type":"visualization"}],"type":"dashboard","updated_at":"2023-02-26T23:44:09.855Z","version":"WzczLDdd"} +{"exportedCount":9,"missingRefCount":0,"missingReferences":[]} \ No newline at end of file From baf1edbd8b0c3dcf8eb631ce438e55a5400a423a Mon Sep 17 00:00:00 2001 From: Simeon Widdis Date: Mon, 10 Apr 2023 16:20:24 -0700 Subject: [PATCH 18/40] Modify template http dashboard Signed-off-by: Simeon Widdis --- .../template-dashboards/http.ndjson | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/scripts/integrations-cli/template-dashboards/http.ndjson b/scripts/integrations-cli/template-dashboards/http.ndjson index 71baa411c..25f8db70a 100644 --- a/scripts/integrations-cli/template-dashboards/http.ndjson +++ b/scripts/integrations-cli/template-dashboards/http.ndjson @@ -1,10 +1,10 @@ -{"attributes":{"fields":"[{\"count\":0,\"name\":\"@timestamp\",\"type\":\"date\",\"esTypes\":[\"date\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"_id\",\"type\":\"string\",\"esTypes\":[\"_id\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"count\":0,\"name\":\"_index\",\"type\":\"string\",\"esTypes\":[\"_index\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"count\":0,\"name\":\"_score\",\"type\":\"number\",\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"_source\",\"type\":\"_source\",\"esTypes\":[\"_source\"],\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"_type\",\"type\":\"string\",\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"attributes.data_stream.dataset\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"attributes.data_stream.dataset.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"attributes.data_stream.dataset\"}}},{\"count\":0,\"name\":\"attributes.data_stream.namespace\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"attributes.data_stream.namespace.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"attributes.data_stream.namespace\"}}},{\"count\":0,\"name\":\"attributes.data_stream.type\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"attributes.data_stream.type.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"attributes.data_stream.type\"}}},{\"count\":0,\"name\":\"body\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"body.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"body\"}}},{\"count\":0,\"name\":\"communication.source.address\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"communication.source.address.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"communication.source.address\"}}},{\"count\":0,\"name\":\"communication.source.ip\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"communication.source.ip.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"communication.source.ip\"}}},{\"count\":0,\"name\":\"event.category\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"event.category.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"event.category\"}}},{\"count\":0,\"name\":\"event.domain\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"event.domain.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"event.domain\"}}},{\"count\":0,\"name\":\"event.kind\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"event.kind.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"event.kind\"}}},{\"count\":0,\"name\":\"event.name\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"event.name.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"event.name\"}}},{\"count\":0,\"name\":\"event.result\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"event.result.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"event.result\"}}},{\"count\":0,\"name\":\"event.type\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"event.type.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"event.type\"}}},{\"count\":0,\"name\":\"http.flavor\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"http.flavor.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"http.flavor\"}}},{\"count\":0,\"name\":\"http.request.method\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"http.request.method.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"http.request.method\"}}},{\"count\":0,\"name\":\"http.response.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"http.response.status_code\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"http.response.status_code.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"http.response.status_code\"}}},{\"count\":0,\"name\":\"http.url\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"http.url\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"http.url\"}}},{\"count\":0,\"name\":\"observerTime\",\"type\":\"date\",\"esTypes\":[\"date\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"span_id\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"span_id.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"span_id\"}}},{\"count\":0,\"name\":\"trace_id\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"trace_id.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"trace_id\"}}}]","timeFieldName":"@timestamp","title":"sso_logs-*-*"},"id":"47892350-b495-11ed-af0a-cf5c93b5a3b6","migrationVersion":{"index-pattern":"7.6.0"},"references":[],"type":"index-pattern","updated_at":"2023-02-26T00:34:36.592Z","version":"WzYxLDdd"} -{"attributes":{"columns":["http.request.method","http.response.status_code"],"description":"","hits":0,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\n \"highlightAll\": true,\n \"version\": true,\n \"query\": {\n \"query\": \"event.domain:nginx.access\",\n \"language\": \"kuery\"\n },\n \"filter\": [],\n \"indexRefName\": \"kibanaSavedObjectMeta.searchSourceJSON.index\"\n}"},"sort":[],"title":"[NGINX Core Logs 1.0] Nginx Access Logs","version":1},"id":"d80e05b2-518c-4c3d-9651-4c9d8632dce4","migrationVersion":{"search":"7.9.3"},"references":[{"id":"47892350-b495-11ed-af0a-cf5c93b5a3b6","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"type":"search","updated_at":"2023-02-26T00:34:36.592Z","version":"WzYyLDdd"} -{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[]}"},"savedSearchRefName":"search_0","title":"[NGINX Core Logs 1.0] Response codes over time","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"[NGINX Core Logs 1.0] Response codes over time\",\"type\":\"histogram\",\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"params\":{},\"schema\":\"metric\"},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"params\":{\"field\":\"@timestamp\",\"timeRange\":{\"from\":\"now-24h\",\"to\":\"now\"},\"useNormalizedOpenSearchInterval\":true,\"scaleMetricValues\":false,\"interval\":\"auto\",\"drop_partials\":false,\"min_doc_count\":1,\"extended_bounds\":{}},\"schema\":\"segment\"},{\"id\":\"3\",\"enabled\":true,\"type\":\"filters\",\"params\":{\"filters\":[{\"input\":{\"query\":\"http.response.status_code:[200 TO 299]\",\"language\":\"lucene\"},\"label\":\"200s\"},{\"input\":{\"query\":\"http.response.status_code:[300 TO 399]\",\"language\":\"lucene\"},\"label\":\"300s\"},{\"input\":{\"query\":\"http.response.status_code:[400 TO 499]\",\"language\":\"lucene\"},\"label\":\"400s\"},{\"input\":{\"query\":\"http.response.status_code:[500 TO 599]\",\"language\":\"lucene\"},\"label\":\"500s\"},{\"input\":{\"query\":\"http.response.status_code:0\",\"language\":\"lucene\"},\"label\":\"0\"}]},\"schema\":\"group\"}],\"params\":{\"type\":\"histogram\",\"grid\":{\"categoryLines\":false},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"filter\":true,\"truncate\":100},\"title\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Count\"}}],\"seriesParams\":[{\"show\":true,\"type\":\"histogram\",\"mode\":\"stacked\",\"data\":{\"label\":\"Count\",\"id\":\"1\"},\"valueAxis\":\"ValueAxis-1\",\"drawLinesBetweenPoints\":true,\"lineWidth\":2,\"showCircles\":true}],\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"times\":[],\"addTimeMarker\":false,\"labels\":{\"show\":false},\"thresholdLine\":{\"show\":false,\"value\":10,\"width\":1,\"style\":\"full\",\"color\":\"#E7664C\"}}}"},"id":"3b49a65d-54d8-483d-a8f0-3d7c855e1ecf","migrationVersion":{"visualization":"7.10.0"},"references":[{"id":"d80e05b2-518c-4c3d-9651-4c9d8632dce4","name":"search_0","type":"search"}],"type":"visualization","updated_at":"2023-02-26T00:34:36.592Z","version":"WzYzLDdd"} -{"attributes":{"columns":["_source"],"description":"","hits":0,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\n \"highlightAll\": true,\n \"query\": {\n \"query\": \"http.response.status_code >= 300 and event.domain:nginx.access\",\n \"language\": \"kuery\"\n },\n \"version\": true,\n \"highlight\": {\n \"post_tags\": [\n \"@/kibana-highlighted-field@\"\n ],\n \"fields\": {\n \"*\": {}\n },\n \"pre_tags\": [\n \"@kibana-highlighted-field@\"\n ],\n \"require_field_match\": false,\n \"fragment_size\": 2147483647\n },\n \"filter\": [],\n \"indexRefName\": \"kibanaSavedObjectMeta.searchSourceJSON.index\"\n}"},"sort":[["@timestamp","desc"]],"title":"[NGINX Core Logs 1.0] Nginx Error Logs","version":1},"id":"9f820fbe-ddde-43a2-9402-30bd295c97f6","migrationVersion":{"search":"7.9.3"},"references":[{"id":"47892350-b495-11ed-af0a-cf5c93b5a3b6","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"type":"search","updated_at":"2023-02-26T00:34:36.592Z","version":"WzY0LDdd"} -{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[]}"},"savedSearchRefName":"search_0","title":"[NGINX Core Logs 1.0] Errors over time","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"[NGINX Core Logs 1.0] Errors over time\",\"type\":\"histogram\",\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"params\":{},\"schema\":\"metric\"},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"params\":{\"field\":\"@timestamp\",\"timeRange\":{\"from\":\"now-24h\",\"to\":\"now\"},\"useNormalizedOpenSearchInterval\":true,\"scaleMetricValues\":false,\"interval\":\"auto\",\"drop_partials\":false,\"min_doc_count\":1,\"extended_bounds\":{}},\"schema\":\"segment\"}],\"params\":{\"type\":\"histogram\",\"grid\":{\"categoryLines\":false},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"filter\":true,\"truncate\":100},\"title\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Count\"}}],\"seriesParams\":[{\"show\":true,\"type\":\"histogram\",\"mode\":\"stacked\",\"data\":{\"label\":\"Count\",\"id\":\"1\"},\"valueAxis\":\"ValueAxis-1\",\"drawLinesBetweenPoints\":true,\"lineWidth\":2,\"showCircles\":true}],\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"times\":[],\"addTimeMarker\":false,\"labels\":{\"show\":false},\"thresholdLine\":{\"show\":false,\"value\":10,\"width\":1,\"style\":\"full\",\"color\":\"#E7664C\"}}}"},"id":"865e577b-634b-4a65-b9d6-7e324c395d18","migrationVersion":{"visualization":"7.10.0"},"references":[{"id":"9f820fbe-ddde-43a2-9402-30bd295c97f6","name":"search_0","type":"search"}],"type":"visualization","updated_at":"2023-02-26T00:34:36.592Z","version":"WzY1LDdd"} -{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}"},"savedSearchRefName":"search_0","title":"Top Paths","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"Top Paths\",\"type\":\"table\",\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"params\":{},\"schema\":\"metric\"},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"params\":{\"field\":\"http.url\",\"orderBy\":\"1\",\"order\":\"desc\",\"size\":10,\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\",\"customLabel\":\"Paths\"},\"schema\":\"bucket\"}],\"params\":{\"perPage\":10,\"showPartialRows\":false,\"showMetricsAtAllLevels\":false,\"showTotal\":false,\"totalFunc\":\"sum\",\"percentageCol\":\"\"}}"},"id":"dc1803f0-b478-11ed-9063-ebe46f9ac203","migrationVersion":{"visualization":"7.10.0"},"references":[{"id":"d80e05b2-518c-4c3d-9651-4c9d8632dce4","name":"search_0","type":"search"}],"type":"visualization","updated_at":"2023-02-26T00:34:36.592Z","version":"WzY2LDdd"} -{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}"},"savedSearchRefName":"search_0","title":"Data Volume","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"Data Volume\",\"type\":\"area\",\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"sum\",\"params\":{\"field\":\"http.response.bytes\",\"customLabel\":\"Response Bytes\"},\"schema\":\"metric\"},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"params\":{\"field\":\"observerTime\",\"timeRange\":{\"from\":\"now-15m\",\"to\":\"now\"},\"useNormalizedOpenSearchInterval\":true,\"scaleMetricValues\":false,\"interval\":\"auto\",\"drop_partials\":false,\"min_doc_count\":1,\"extended_bounds\":{},\"customLabel\":\"\"},\"schema\":\"segment\"}],\"params\":{\"type\":\"area\",\"grid\":{\"categoryLines\":false},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"filter\":true,\"truncate\":100},\"title\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Response Bytes\"}}],\"seriesParams\":[{\"show\":true,\"type\":\"area\",\"mode\":\"stacked\",\"data\":{\"label\":\"Response Bytes\",\"id\":\"1\"},\"drawLinesBetweenPoints\":true,\"lineWidth\":2,\"showCircles\":true,\"interpolate\":\"linear\",\"valueAxis\":\"ValueAxis-1\"}],\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"times\":[],\"addTimeMarker\":false,\"thresholdLine\":{\"show\":false,\"value\":10,\"width\":1,\"style\":\"full\",\"color\":\"#E7664C\"},\"labels\":{}}}"},"id":"99acc580-b47a-11ed-9063-ebe46f9ac203","migrationVersion":{"visualization":"7.10.0"},"references":[{"id":"d80e05b2-518c-4c3d-9651-4c9d8632dce4","name":"search_0","type":"search"}],"type":"visualization","updated_at":"2023-02-26T00:34:36.592Z","version":"WzY3LDdd"} -{"attributes":{"description":"requests per minute aggregation","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"title":"Req-per-min","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"Req-per-min\",\"type\":\"table\",\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"moving_avg\",\"params\":{\"metricAgg\":\"custom\",\"customMetric\":{\"id\":\"1-metric\",\"enabled\":true,\"type\":\"count\",\"params\":{}},\"window\":5,\"script\":\"MovingFunctions.unweightedAvg(values)\"},\"schema\":\"metric\"},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"params\":{\"field\":\"@timestamp\",\"timeRange\":{\"from\":\"2023-02-24T17:25:00.000Z\",\"to\":\"2023-02-24T17:30:00.000Z\"},\"useNormalizedOpenSearchInterval\":true,\"scaleMetricValues\":false,\"interval\":\"m\",\"drop_partials\":false,\"min_doc_count\":0,\"extended_bounds\":{},\"customLabel\":\"Req/Min\"},\"schema\":\"bucket\"}],\"params\":{\"perPage\":10,\"showPartialRows\":false,\"showMetricsAtAllLevels\":false,\"showTotal\":false,\"totalFunc\":\"sum\",\"percentageCol\":\"\"}}"},"id":"01ea64d0-b62f-11ed-a677-43d7aa86763b","migrationVersion":{"visualization":"7.10.0"},"references":[{"id":"47892350-b495-11ed-af0a-cf5c93b5a3b6","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"type":"visualization","updated_at":"2023-02-26T23:40:53.020Z","version":"WzcyLDdd"} -{"attributes":{"description":"Nginx dashboard with basic Observability on access / error logs","hits":0,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[]}"},"optionsJSON":"{\"hidePanelTitles\":false,\"useMargins\":true}","panelsJSON":"[{\"version\":\"2.5.0\",\"gridData\":{\"h\":8,\"i\":\"1f31e50b-06e3-41e6-972e-e4e5fe1a9872\",\"w\":48,\"x\":0,\"y\":0},\"panelIndex\":\"1f31e50b-06e3-41e6-972e-e4e5fe1a9872\",\"embeddableConfig\":{},\"panelRefName\":\"panel_0\"},{\"version\":\"2.5.0\",\"gridData\":{\"h\":9,\"i\":\"d91a8da4-b34b-470a-aca6-9c76b47cd6fb\",\"w\":24,\"x\":0,\"y\":8},\"panelIndex\":\"d91a8da4-b34b-470a-aca6-9c76b47cd6fb\",\"embeddableConfig\":{},\"panelRefName\":\"panel_1\"},{\"version\":\"2.5.0\",\"gridData\":{\"h\":15,\"i\":\"27149e5a-3a77-4f3c-800e-8a160c3765f4\",\"w\":24,\"x\":24,\"y\":8},\"panelIndex\":\"27149e5a-3a77-4f3c-800e-8a160c3765f4\",\"embeddableConfig\":{},\"panelRefName\":\"panel_2\"},{\"version\":\"2.5.0\",\"gridData\":{\"x\":0,\"y\":17,\"w\":24,\"h\":15,\"i\":\"4d8c2aa7-159c-4a1a-80ff-00a9299056ce\"},\"panelIndex\":\"4d8c2aa7-159c-4a1a-80ff-00a9299056ce\",\"embeddableConfig\":{},\"panelRefName\":\"panel_3\"},{\"version\":\"2.5.0\",\"gridData\":{\"x\":24,\"y\":23,\"w\":24,\"h\":15,\"i\":\"800b7f19-f50c-417f-8987-21b930531cbe\"},\"panelIndex\":\"800b7f19-f50c-417f-8987-21b930531cbe\",\"embeddableConfig\":{},\"panelRefName\":\"panel_4\"}]","timeRestore":false,"title":"[NGINX Core Logs 1.0] Overview","version":1},"id":"96847220-5261-44d0-89b4-65f3a659f13a","migrationVersion":{"dashboard":"7.9.3"},"references":[{"id":"3b49a65d-54d8-483d-a8f0-3d7c855e1ecf","name":"panel_0","type":"visualization"},{"id":"865e577b-634b-4a65-b9d6-7e324c395d18","name":"panel_1","type":"visualization"},{"id":"dc1803f0-b478-11ed-9063-ebe46f9ac203","name":"panel_2","type":"visualization"},{"id":"99acc580-b47a-11ed-9063-ebe46f9ac203","name":"panel_3","type":"visualization"},{"id":"01ea64d0-b62f-11ed-a677-43d7aa86763b","name":"panel_4","type":"visualization"}],"type":"dashboard","updated_at":"2023-02-26T23:44:09.855Z","version":"WzczLDdd"} +{"attributes":{"fields":"[{\"count\":0,\"name\":\"@timestamp\",\"type\":\"date\",\"esTypes\":[\"date\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"_id\",\"type\":\"string\",\"esTypes\":[\"_id\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"count\":0,\"name\":\"_index\",\"type\":\"string\",\"esTypes\":[\"_index\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"count\":0,\"name\":\"_score\",\"type\":\"number\",\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"_source\",\"type\":\"_source\",\"esTypes\":[\"_source\"],\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"_type\",\"type\":\"string\",\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"attributes.data_stream.dataset\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"attributes.data_stream.dataset.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"attributes.data_stream.dataset\"}}},{\"count\":0,\"name\":\"attributes.data_stream.namespace\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"attributes.data_stream.namespace.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"attributes.data_stream.namespace\"}}},{\"count\":0,\"name\":\"attributes.data_stream.type\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"attributes.data_stream.type.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"attributes.data_stream.type\"}}},{\"count\":0,\"name\":\"body\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"body.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"body\"}}},{\"count\":0,\"name\":\"communication.source.address\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"communication.source.address.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"communication.source.address\"}}},{\"count\":0,\"name\":\"communication.source.ip\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"communication.source.ip.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"communication.source.ip\"}}},{\"count\":0,\"name\":\"event.category\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"event.category.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"event.category\"}}},{\"count\":0,\"name\":\"event.domain\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"event.domain.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"event.domain\"}}},{\"count\":0,\"name\":\"event.kind\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"event.kind.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"event.kind\"}}},{\"count\":0,\"name\":\"event.name\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"event.name.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"event.name\"}}},{\"count\":0,\"name\":\"event.result\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"event.result.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"event.result\"}}},{\"count\":0,\"name\":\"event.type\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"event.type.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"event.type\"}}},{\"count\":0,\"name\":\"http.flavor\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"http.flavor.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"http.flavor\"}}},{\"count\":0,\"name\":\"http.request.method\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"http.request.method.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"http.request.method\"}}},{\"count\":0,\"name\":\"http.response.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"http.response.status_code\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"http.response.status_code.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"http.response.status_code\"}}},{\"count\":0,\"name\":\"http.url\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"http.url\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"http.url\"}}},{\"count\":0,\"name\":\"observerTime\",\"type\":\"date\",\"esTypes\":[\"date\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"span_id\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"span_id.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"span_id\"}}},{\"count\":0,\"name\":\"trace_id\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"trace_id.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"trace_id\"}}}]","timeFieldName":"@timestamp","title":"sso_logs-*-*"},"id":"47892350-b495-11ed-af0a-cf5c93b5a3b6","migrationVersion":{"index-pattern":"7.6.0"},"references":[],"type":"index-pattern","updated_at":"2023-04-10T22:57:51.792Z","version":"WzEsMV0="} +{"attributes":{"columns":["http.request.method","http.response.status_code"],"description":"","hits":0,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\n \"highlightAll\": true,\n \"version\": true,\n \"query\": {\n \"query\": \"event.domain:nginx.access\",\n \"language\": \"kuery\"\n },\n \"filter\": [],\n \"indexRefName\": \"kibanaSavedObjectMeta.searchSourceJSON.index\"\n}"},"sort":[],"title":"[NGINX Core Logs 1.0] Nginx Access Logs","version":1},"id":"d80e05b2-518c-4c3d-9651-4c9d8632dce4","migrationVersion":{"search":"7.9.3"},"references":[{"id":"47892350-b495-11ed-af0a-cf5c93b5a3b6","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"type":"search","updated_at":"2023-04-10T22:57:51.792Z","version":"WzIsMV0="} +{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[]}"},"savedSearchRefName":"search_0","title":"[NGINX Core Logs 1.0] Response codes over time","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"[NGINX Core Logs 1.0] Response codes over time\",\"type\":\"histogram\",\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"params\":{},\"schema\":\"metric\"},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"params\":{\"field\":\"@timestamp\",\"timeRange\":{\"from\":\"now-24h\",\"to\":\"now\"},\"useNormalizedOpenSearchInterval\":true,\"scaleMetricValues\":false,\"interval\":\"auto\",\"drop_partials\":false,\"min_doc_count\":1,\"extended_bounds\":{}},\"schema\":\"segment\"},{\"id\":\"3\",\"enabled\":true,\"type\":\"filters\",\"params\":{\"filters\":[{\"input\":{\"query\":\"http.response.status_code:[200 TO 299]\",\"language\":\"lucene\"},\"label\":\"200s\"},{\"input\":{\"query\":\"http.response.status_code:[300 TO 399]\",\"language\":\"lucene\"},\"label\":\"300s\"},{\"input\":{\"query\":\"http.response.status_code:[400 TO 499]\",\"language\":\"lucene\"},\"label\":\"400s\"},{\"input\":{\"query\":\"http.response.status_code:[500 TO 599]\",\"language\":\"lucene\"},\"label\":\"500s\"},{\"input\":{\"query\":\"http.response.status_code:0\",\"language\":\"lucene\"},\"label\":\"0\"}]},\"schema\":\"group\"}],\"params\":{\"type\":\"histogram\",\"grid\":{\"categoryLines\":false},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"filter\":true,\"truncate\":100},\"title\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Count\"}}],\"seriesParams\":[{\"show\":true,\"type\":\"histogram\",\"mode\":\"stacked\",\"data\":{\"label\":\"Count\",\"id\":\"1\"},\"valueAxis\":\"ValueAxis-1\",\"drawLinesBetweenPoints\":true,\"lineWidth\":2,\"showCircles\":true}],\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"times\":[],\"addTimeMarker\":false,\"labels\":{\"show\":false},\"thresholdLine\":{\"show\":false,\"value\":10,\"width\":1,\"style\":\"full\",\"color\":\"#E7664C\"}}}"},"id":"3b49a65d-54d8-483d-a8f0-3d7c855e1ecf","migrationVersion":{"visualization":"7.10.0"},"references":[{"id":"d80e05b2-518c-4c3d-9651-4c9d8632dce4","name":"search_0","type":"search"}],"type":"visualization","updated_at":"2023-04-10T22:57:51.792Z","version":"WzMsMV0="} +{"attributes":{"columns":["_source"],"description":"","hits":0,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\n \"highlightAll\": true,\n \"query\": {\n \"query\": \"http.response.status_code >= 300 and event.domain:nginx.access\",\n \"language\": \"kuery\"\n },\n \"version\": true,\n \"highlight\": {\n \"post_tags\": [\n \"@/kibana-highlighted-field@\"\n ],\n \"fields\": {\n \"*\": {}\n },\n \"pre_tags\": [\n \"@kibana-highlighted-field@\"\n ],\n \"require_field_match\": false,\n \"fragment_size\": 2147483647\n },\n \"filter\": [],\n \"indexRefName\": \"kibanaSavedObjectMeta.searchSourceJSON.index\"\n}"},"sort":[["@timestamp","desc"]],"title":"[NGINX Core Logs 1.0] Nginx Error Logs","version":1},"id":"9f820fbe-ddde-43a2-9402-30bd295c97f6","migrationVersion":{"search":"7.9.3"},"references":[{"id":"47892350-b495-11ed-af0a-cf5c93b5a3b6","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"type":"search","updated_at":"2023-04-10T22:57:51.792Z","version":"WzQsMV0="} +{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[]}"},"savedSearchRefName":"search_0","title":"[NGINX Core Logs 1.0] Errors over time","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"[NGINX Core Logs 1.0] Errors over time\",\"type\":\"histogram\",\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"params\":{},\"schema\":\"metric\"},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"params\":{\"field\":\"@timestamp\",\"timeRange\":{\"from\":\"now-15m\",\"to\":\"now\"},\"useNormalizedOpenSearchInterval\":true,\"scaleMetricValues\":false,\"interval\":\"auto\",\"drop_partials\":false,\"min_doc_count\":1,\"extended_bounds\":{}},\"schema\":\"segment\"}],\"params\":{\"type\":\"histogram\",\"grid\":{\"categoryLines\":false},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"filter\":true,\"truncate\":100},\"title\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Count\"}}],\"seriesParams\":[{\"show\":true,\"type\":\"histogram\",\"mode\":\"stacked\",\"data\":{\"label\":\"Count\",\"id\":\"1\"},\"valueAxis\":\"ValueAxis-1\",\"drawLinesBetweenPoints\":true,\"lineWidth\":2,\"showCircles\":true}],\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"times\":[],\"addTimeMarker\":false,\"labels\":{\"show\":false},\"thresholdLine\":{\"show\":false,\"value\":10,\"width\":1,\"style\":\"full\",\"color\":\"#E7664C\"}}}"},"id":"865e577b-634b-4a65-b9d6-7e324c395d18","migrationVersion":{"visualization":"7.10.0"},"references":[{"id":"9f820fbe-ddde-43a2-9402-30bd295c97f6","name":"search_0","type":"search"}],"type":"visualization","updated_at":"2023-04-10T23:06:46.320Z","version":"WzEyLDFd"} +{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}"},"savedSearchRefName":"search_0","title":"Top Paths","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"Top Paths\",\"type\":\"table\",\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"params\":{},\"schema\":\"metric\"},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"params\":{\"field\":\"http.url\",\"orderBy\":\"1\",\"order\":\"desc\",\"size\":9,\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\"},\"schema\":\"bucket\"}],\"params\":{\"perPage\":10,\"showPartialRows\":false,\"showMetricsAtAllLevels\":false,\"showTotal\":false,\"totalFunc\":\"sum\",\"percentageCol\":\"\"}}"},"id":"dc1803f0-b478-11ed-9063-ebe46f9ac203","migrationVersion":{"visualization":"7.10.0"},"references":[{"id":"d80e05b2-518c-4c3d-9651-4c9d8632dce4","name":"search_0","type":"search"}],"type":"visualization","updated_at":"2023-04-10T23:18:14.094Z","version":"WzE1LDFd"} +{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}"},"savedSearchRefName":"search_0","title":"Data Volume","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"Data Volume\",\"type\":\"area\",\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"sum\",\"params\":{\"field\":\"http.response.bytes\",\"customLabel\":\"Response Bytes\"},\"schema\":\"metric\"},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"params\":{\"field\":\"observerTime\",\"timeRange\":{\"from\":\"now-15m\",\"to\":\"now\"},\"useNormalizedOpenSearchInterval\":true,\"scaleMetricValues\":false,\"interval\":\"auto\",\"drop_partials\":false,\"min_doc_count\":1,\"extended_bounds\":{},\"customLabel\":\"\"},\"schema\":\"segment\"}],\"params\":{\"type\":\"area\",\"grid\":{\"categoryLines\":false},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"filter\":true,\"truncate\":100},\"title\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Response Bytes\"}}],\"seriesParams\":[{\"show\":true,\"type\":\"area\",\"mode\":\"stacked\",\"data\":{\"label\":\"Response Bytes\",\"id\":\"1\"},\"drawLinesBetweenPoints\":true,\"lineWidth\":2,\"showCircles\":true,\"interpolate\":\"linear\",\"valueAxis\":\"ValueAxis-1\"}],\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"times\":[],\"addTimeMarker\":false,\"thresholdLine\":{\"show\":false,\"value\":10,\"width\":1,\"style\":\"full\",\"color\":\"#E7664C\"},\"labels\":{}}}"},"id":"99acc580-b47a-11ed-9063-ebe46f9ac203","migrationVersion":{"visualization":"7.10.0"},"references":[{"id":"d80e05b2-518c-4c3d-9651-4c9d8632dce4","name":"search_0","type":"search"}],"type":"visualization","updated_at":"2023-04-10T22:57:51.792Z","version":"WzcsMV0="} +{"attributes":{"description":"requests per minute aggregation","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"title":"Req-per-min","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"Req-per-min\",\"type\":\"table\",\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"moving_avg\",\"params\":{\"metricAgg\":\"custom\",\"customMetric\":{\"id\":\"1-metric\",\"enabled\":true,\"type\":\"count\",\"params\":{}},\"window\":5,\"script\":\"MovingFunctions.unweightedAvg(values)\",\"customLabel\":\"Requests (Moving Avg.)\"},\"schema\":\"metric\"},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"params\":{\"field\":\"@timestamp\",\"timeRange\":{\"from\":\"now-15m\",\"to\":\"now\"},\"useNormalizedOpenSearchInterval\":true,\"scaleMetricValues\":false,\"interval\":\"m\",\"drop_partials\":false,\"min_doc_count\":0,\"extended_bounds\":{},\"customLabel\":\"Req/Min\"},\"schema\":\"bucket\"}],\"params\":{\"perPage\":10,\"showPartialRows\":false,\"showMetricsAtAllLevels\":false,\"showTotal\":false,\"totalFunc\":\"sum\",\"percentageCol\":\"\"}}"},"id":"01ea64d0-b62f-11ed-a677-43d7aa86763b","migrationVersion":{"visualization":"7.10.0"},"references":[{"id":"47892350-b495-11ed-af0a-cf5c93b5a3b6","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"type":"visualization","updated_at":"2023-04-10T23:10:20.969Z","version":"WzEzLDFd"} +{"attributes":{"description":"Basic template for HTTP-based observability dashboards","hits":0,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[]}"},"optionsJSON":"{\"hidePanelTitles\":false,\"useMargins\":true}","panelsJSON":"[{\"embeddableConfig\":{\"hidePanelTitles\":false,\"title\":\"[HTTP Logs 1.0] Response codes over time\"},\"gridData\":{\"h\":8,\"i\":\"1f31e50b-06e3-41e6-972e-e4e5fe1a9872\",\"w\":48,\"x\":0,\"y\":0},\"panelIndex\":\"1f31e50b-06e3-41e6-972e-e4e5fe1a9872\",\"title\":\"[HTTP Logs 1.0] Response codes over time\",\"version\":\"2.5.0\",\"panelRefName\":\"panel_0\"},{\"embeddableConfig\":{\"hidePanelTitles\":false,\"title\":\"[HTTP Logs 1.0] Errors over time\"},\"gridData\":{\"h\":9,\"i\":\"d91a8da4-b34b-470a-aca6-9c76b47cd6fb\",\"w\":24,\"x\":0,\"y\":8},\"panelIndex\":\"d91a8da4-b34b-470a-aca6-9c76b47cd6fb\",\"title\":\"[HTTP Logs 1.0] Errors over time\",\"version\":\"2.5.0\",\"panelRefName\":\"panel_1\"},{\"embeddableConfig\":{\"hidePanelTitles\":false,\"title\":\"[HTTP Logs 1.0] Top Paths\"},\"gridData\":{\"h\":15,\"i\":\"27149e5a-3a77-4f3c-800e-8a160c3765f4\",\"w\":24,\"x\":24,\"y\":8},\"panelIndex\":\"27149e5a-3a77-4f3c-800e-8a160c3765f4\",\"title\":\"[HTTP Logs 1.0] Top Paths\",\"version\":\"2.5.0\",\"panelRefName\":\"panel_2\"},{\"embeddableConfig\":{\"hidePanelTitles\":false,\"title\":\"[HTTP Logs 1.0] Data Volume\"},\"gridData\":{\"h\":15,\"i\":\"4d8c2aa7-159c-4a1a-80ff-00a9299056ce\",\"w\":24,\"x\":0,\"y\":17},\"panelIndex\":\"4d8c2aa7-159c-4a1a-80ff-00a9299056ce\",\"title\":\"[HTTP Logs 1.0] Data Volume\",\"version\":\"2.5.0\",\"panelRefName\":\"panel_3\"},{\"embeddableConfig\":{\"hidePanelTitles\":false,\"title\":\"[HTTP Logs 1.0] Requests per Minute\"},\"gridData\":{\"h\":15,\"i\":\"800b7f19-f50c-417f-8987-21b930531cbe\",\"w\":24,\"x\":24,\"y\":23},\"panelIndex\":\"800b7f19-f50c-417f-8987-21b930531cbe\",\"title\":\"[HTTP Logs 1.0] Requests per Minute\",\"version\":\"2.5.0\",\"panelRefName\":\"panel_4\"}]","refreshInterval":{"pause":true,"value":0},"timeFrom":"now-15m","timeRestore":true,"timeTo":"now","title":"[HTTP Logs 1.0] Overview","version":1},"id":"96847220-5261-44d0-89b4-65f3a659f13a","migrationVersion":{"dashboard":"7.9.3"},"references":[{"id":"3b49a65d-54d8-483d-a8f0-3d7c855e1ecf","name":"panel_0","type":"visualization"},{"id":"865e577b-634b-4a65-b9d6-7e324c395d18","name":"panel_1","type":"visualization"},{"id":"dc1803f0-b478-11ed-9063-ebe46f9ac203","name":"panel_2","type":"visualization"},{"id":"99acc580-b47a-11ed-9063-ebe46f9ac203","name":"panel_3","type":"visualization"},{"id":"01ea64d0-b62f-11ed-a677-43d7aa86763b","name":"panel_4","type":"visualization"}],"type":"dashboard","updated_at":"2023-04-10T23:19:07.325Z","version":"WzE2LDFd"} {"exportedCount":9,"missingRefCount":0,"missingReferences":[]} \ No newline at end of file From 00cc117a3f490482fed75268dc85aafea26a8cdf Mon Sep 17 00:00:00 2001 From: Simeon Widdis Date: Mon, 10 Apr 2023 17:19:01 -0700 Subject: [PATCH 19/40] Modify dashboards and add upload script Signed-off-by: Simeon Widdis --- .../template-dashboards/http.ndjson | 12 ++++++------ scripts/integrations-cli/upload.sh | 13 +++++++++++++ 2 files changed, 19 insertions(+), 6 deletions(-) create mode 100644 scripts/integrations-cli/upload.sh diff --git a/scripts/integrations-cli/template-dashboards/http.ndjson b/scripts/integrations-cli/template-dashboards/http.ndjson index 25f8db70a..1c168fbe2 100644 --- a/scripts/integrations-cli/template-dashboards/http.ndjson +++ b/scripts/integrations-cli/template-dashboards/http.ndjson @@ -1,9 +1,9 @@ -{"attributes":{"fields":"[{\"count\":0,\"name\":\"@timestamp\",\"type\":\"date\",\"esTypes\":[\"date\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"_id\",\"type\":\"string\",\"esTypes\":[\"_id\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"count\":0,\"name\":\"_index\",\"type\":\"string\",\"esTypes\":[\"_index\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"count\":0,\"name\":\"_score\",\"type\":\"number\",\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"_source\",\"type\":\"_source\",\"esTypes\":[\"_source\"],\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"_type\",\"type\":\"string\",\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"attributes.data_stream.dataset\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"attributes.data_stream.dataset.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"attributes.data_stream.dataset\"}}},{\"count\":0,\"name\":\"attributes.data_stream.namespace\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"attributes.data_stream.namespace.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"attributes.data_stream.namespace\"}}},{\"count\":0,\"name\":\"attributes.data_stream.type\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"attributes.data_stream.type.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"attributes.data_stream.type\"}}},{\"count\":0,\"name\":\"body\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"body.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"body\"}}},{\"count\":0,\"name\":\"communication.source.address\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"communication.source.address.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"communication.source.address\"}}},{\"count\":0,\"name\":\"communication.source.ip\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"communication.source.ip.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"communication.source.ip\"}}},{\"count\":0,\"name\":\"event.category\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"event.category.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"event.category\"}}},{\"count\":0,\"name\":\"event.domain\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"event.domain.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"event.domain\"}}},{\"count\":0,\"name\":\"event.kind\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"event.kind.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"event.kind\"}}},{\"count\":0,\"name\":\"event.name\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"event.name.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"event.name\"}}},{\"count\":0,\"name\":\"event.result\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"event.result.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"event.result\"}}},{\"count\":0,\"name\":\"event.type\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"event.type.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"event.type\"}}},{\"count\":0,\"name\":\"http.flavor\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"http.flavor.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"http.flavor\"}}},{\"count\":0,\"name\":\"http.request.method\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"http.request.method.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"http.request.method\"}}},{\"count\":0,\"name\":\"http.response.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"http.response.status_code\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"http.response.status_code.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"http.response.status_code\"}}},{\"count\":0,\"name\":\"http.url\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"http.url\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"http.url\"}}},{\"count\":0,\"name\":\"observerTime\",\"type\":\"date\",\"esTypes\":[\"date\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"span_id\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"span_id.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"span_id\"}}},{\"count\":0,\"name\":\"trace_id\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"trace_id.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"trace_id\"}}}]","timeFieldName":"@timestamp","title":"sso_logs-*-*"},"id":"47892350-b495-11ed-af0a-cf5c93b5a3b6","migrationVersion":{"index-pattern":"7.6.0"},"references":[],"type":"index-pattern","updated_at":"2023-04-10T22:57:51.792Z","version":"WzEsMV0="} -{"attributes":{"columns":["http.request.method","http.response.status_code"],"description":"","hits":0,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\n \"highlightAll\": true,\n \"version\": true,\n \"query\": {\n \"query\": \"event.domain:nginx.access\",\n \"language\": \"kuery\"\n },\n \"filter\": [],\n \"indexRefName\": \"kibanaSavedObjectMeta.searchSourceJSON.index\"\n}"},"sort":[],"title":"[NGINX Core Logs 1.0] Nginx Access Logs","version":1},"id":"d80e05b2-518c-4c3d-9651-4c9d8632dce4","migrationVersion":{"search":"7.9.3"},"references":[{"id":"47892350-b495-11ed-af0a-cf5c93b5a3b6","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"type":"search","updated_at":"2023-04-10T22:57:51.792Z","version":"WzIsMV0="} -{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[]}"},"savedSearchRefName":"search_0","title":"[NGINX Core Logs 1.0] Response codes over time","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"[NGINX Core Logs 1.0] Response codes over time\",\"type\":\"histogram\",\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"params\":{},\"schema\":\"metric\"},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"params\":{\"field\":\"@timestamp\",\"timeRange\":{\"from\":\"now-24h\",\"to\":\"now\"},\"useNormalizedOpenSearchInterval\":true,\"scaleMetricValues\":false,\"interval\":\"auto\",\"drop_partials\":false,\"min_doc_count\":1,\"extended_bounds\":{}},\"schema\":\"segment\"},{\"id\":\"3\",\"enabled\":true,\"type\":\"filters\",\"params\":{\"filters\":[{\"input\":{\"query\":\"http.response.status_code:[200 TO 299]\",\"language\":\"lucene\"},\"label\":\"200s\"},{\"input\":{\"query\":\"http.response.status_code:[300 TO 399]\",\"language\":\"lucene\"},\"label\":\"300s\"},{\"input\":{\"query\":\"http.response.status_code:[400 TO 499]\",\"language\":\"lucene\"},\"label\":\"400s\"},{\"input\":{\"query\":\"http.response.status_code:[500 TO 599]\",\"language\":\"lucene\"},\"label\":\"500s\"},{\"input\":{\"query\":\"http.response.status_code:0\",\"language\":\"lucene\"},\"label\":\"0\"}]},\"schema\":\"group\"}],\"params\":{\"type\":\"histogram\",\"grid\":{\"categoryLines\":false},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"filter\":true,\"truncate\":100},\"title\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Count\"}}],\"seriesParams\":[{\"show\":true,\"type\":\"histogram\",\"mode\":\"stacked\",\"data\":{\"label\":\"Count\",\"id\":\"1\"},\"valueAxis\":\"ValueAxis-1\",\"drawLinesBetweenPoints\":true,\"lineWidth\":2,\"showCircles\":true}],\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"times\":[],\"addTimeMarker\":false,\"labels\":{\"show\":false},\"thresholdLine\":{\"show\":false,\"value\":10,\"width\":1,\"style\":\"full\",\"color\":\"#E7664C\"}}}"},"id":"3b49a65d-54d8-483d-a8f0-3d7c855e1ecf","migrationVersion":{"visualization":"7.10.0"},"references":[{"id":"d80e05b2-518c-4c3d-9651-4c9d8632dce4","name":"search_0","type":"search"}],"type":"visualization","updated_at":"2023-04-10T22:57:51.792Z","version":"WzMsMV0="} -{"attributes":{"columns":["_source"],"description":"","hits":0,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\n \"highlightAll\": true,\n \"query\": {\n \"query\": \"http.response.status_code >= 300 and event.domain:nginx.access\",\n \"language\": \"kuery\"\n },\n \"version\": true,\n \"highlight\": {\n \"post_tags\": [\n \"@/kibana-highlighted-field@\"\n ],\n \"fields\": {\n \"*\": {}\n },\n \"pre_tags\": [\n \"@kibana-highlighted-field@\"\n ],\n \"require_field_match\": false,\n \"fragment_size\": 2147483647\n },\n \"filter\": [],\n \"indexRefName\": \"kibanaSavedObjectMeta.searchSourceJSON.index\"\n}"},"sort":[["@timestamp","desc"]],"title":"[NGINX Core Logs 1.0] Nginx Error Logs","version":1},"id":"9f820fbe-ddde-43a2-9402-30bd295c97f6","migrationVersion":{"search":"7.9.3"},"references":[{"id":"47892350-b495-11ed-af0a-cf5c93b5a3b6","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"type":"search","updated_at":"2023-04-10T22:57:51.792Z","version":"WzQsMV0="} -{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[]}"},"savedSearchRefName":"search_0","title":"[NGINX Core Logs 1.0] Errors over time","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"[NGINX Core Logs 1.0] Errors over time\",\"type\":\"histogram\",\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"params\":{},\"schema\":\"metric\"},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"params\":{\"field\":\"@timestamp\",\"timeRange\":{\"from\":\"now-15m\",\"to\":\"now\"},\"useNormalizedOpenSearchInterval\":true,\"scaleMetricValues\":false,\"interval\":\"auto\",\"drop_partials\":false,\"min_doc_count\":1,\"extended_bounds\":{}},\"schema\":\"segment\"}],\"params\":{\"type\":\"histogram\",\"grid\":{\"categoryLines\":false},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"filter\":true,\"truncate\":100},\"title\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Count\"}}],\"seriesParams\":[{\"show\":true,\"type\":\"histogram\",\"mode\":\"stacked\",\"data\":{\"label\":\"Count\",\"id\":\"1\"},\"valueAxis\":\"ValueAxis-1\",\"drawLinesBetweenPoints\":true,\"lineWidth\":2,\"showCircles\":true}],\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"times\":[],\"addTimeMarker\":false,\"labels\":{\"show\":false},\"thresholdLine\":{\"show\":false,\"value\":10,\"width\":1,\"style\":\"full\",\"color\":\"#E7664C\"}}}"},"id":"865e577b-634b-4a65-b9d6-7e324c395d18","migrationVersion":{"visualization":"7.10.0"},"references":[{"id":"9f820fbe-ddde-43a2-9402-30bd295c97f6","name":"search_0","type":"search"}],"type":"visualization","updated_at":"2023-04-10T23:06:46.320Z","version":"WzEyLDFd"} -{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}"},"savedSearchRefName":"search_0","title":"Top Paths","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"Top Paths\",\"type\":\"table\",\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"params\":{},\"schema\":\"metric\"},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"params\":{\"field\":\"http.url\",\"orderBy\":\"1\",\"order\":\"desc\",\"size\":9,\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\"},\"schema\":\"bucket\"}],\"params\":{\"perPage\":10,\"showPartialRows\":false,\"showMetricsAtAllLevels\":false,\"showTotal\":false,\"totalFunc\":\"sum\",\"percentageCol\":\"\"}}"},"id":"dc1803f0-b478-11ed-9063-ebe46f9ac203","migrationVersion":{"visualization":"7.10.0"},"references":[{"id":"d80e05b2-518c-4c3d-9651-4c9d8632dce4","name":"search_0","type":"search"}],"type":"visualization","updated_at":"2023-04-10T23:18:14.094Z","version":"WzE1LDFd"} +{"attributes":{"fields":"[{\"count\":0,\"name\":\"@timestamp\",\"type\":\"date\",\"esTypes\":[\"date\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"_id\",\"type\":\"string\",\"esTypes\":[\"_id\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"count\":0,\"name\":\"_index\",\"type\":\"string\",\"esTypes\":[\"_index\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"count\":0,\"name\":\"_score\",\"type\":\"number\",\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"_source\",\"type\":\"_source\",\"esTypes\":[\"_source\"],\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"_type\",\"type\":\"string\",\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"attributes.data_stream.dataset\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"attributes.data_stream.dataset.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"attributes.data_stream.dataset\"}}},{\"count\":0,\"name\":\"attributes.data_stream.namespace\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"attributes.data_stream.namespace.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"attributes.data_stream.namespace\"}}},{\"count\":0,\"name\":\"attributes.data_stream.type\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"attributes.data_stream.type.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"attributes.data_stream.type\"}}},{\"count\":0,\"name\":\"body\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"body.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"body\"}}},{\"count\":0,\"name\":\"communication.source.address\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"communication.source.address.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"communication.source.address\"}}},{\"count\":0,\"name\":\"communication.source.ip\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"communication.source.ip.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"communication.source.ip\"}}},{\"count\":0,\"name\":\"event.category\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"event.category.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"event.category\"}}},{\"count\":0,\"name\":\"event.domain\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"event.domain.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"event.domain\"}}},{\"count\":0,\"name\":\"event.kind\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"event.kind.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"event.kind\"}}},{\"count\":0,\"name\":\"event.name\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"event.name.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"event.name\"}}},{\"count\":0,\"name\":\"event.result\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"event.result.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"event.result\"}}},{\"count\":0,\"name\":\"event.type\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"event.type.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"event.type\"}}},{\"count\":0,\"name\":\"http.flavor\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"http.flavor.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"http.flavor\"}}},{\"count\":0,\"name\":\"http.request.method\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"http.request.method.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"http.request.method\"}}},{\"count\":0,\"name\":\"http.response.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"http.response.status_code\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"http.response.status_code.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"http.response.status_code\"}}},{\"count\":0,\"name\":\"http.url\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"http.url.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"http.url\"}}},{\"count\":0,\"name\":\"observerTime\",\"type\":\"date\",\"esTypes\":[\"date\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"span_id\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"span_id.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"span_id\"}}},{\"count\":0,\"name\":\"trace_id\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"trace_id.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"trace_id\"}}}]","timeFieldName":"@timestamp","title":"sso_logs-*-*"},"id":"sso_logs","migrationVersion":{"index-pattern":"7.6.0"},"references":[],"type":"index-pattern","updated_at":"2023-04-10T23:58:51.826Z","version":"WzQwLDFd"} +{"attributes":{"columns":["http.request.method","http.response.status_code"],"description":"","hits":0,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\n \"highlightAll\": true,\n \"version\": true,\n \"query\": {\n \"query\": \"event.domain:nginx.access\",\n \"language\": \"kuery\"\n },\n \"filter\": [],\n \"indexRefName\": \"kibanaSavedObjectMeta.searchSourceJSON.index\"\n}"},"sort":[],"title":"[Http Logs 1.0] Nginx Access Logs","version":1},"id":"d80e05b2-518c-4c3d-9651-4c9d8632dce4","migrationVersion":{"search":"7.9.3"},"references":[{"id":"47892350-b495-11ed-af0a-cf5c93b5a3b6","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"type":"search","updated_at":"2023-04-10T22:57:51.792Z","version":"WzIsMV0="} +{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[]}"},"savedSearchRefName":"search_0","title":"[Http Logs 1.0] Response codes over time","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"[Http Logs 1.0] Response codes over time\",\"type\":\"histogram\",\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"params\":{},\"schema\":\"metric\"},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"params\":{\"field\":\"@timestamp\",\"timeRange\":{\"from\":\"now-24h\",\"to\":\"now\"},\"useNormalizedOpenSearchInterval\":true,\"scaleMetricValues\":false,\"interval\":\"auto\",\"drop_partials\":false,\"min_doc_count\":1,\"extended_bounds\":{}},\"schema\":\"segment\"},{\"id\":\"3\",\"enabled\":true,\"type\":\"filters\",\"params\":{\"filters\":[{\"input\":{\"query\":\"http.response.status_code:[200 TO 299]\",\"language\":\"lucene\"},\"label\":\"200s\"},{\"input\":{\"query\":\"http.response.status_code:[300 TO 399]\",\"language\":\"lucene\"},\"label\":\"300s\"},{\"input\":{\"query\":\"http.response.status_code:[400 TO 499]\",\"language\":\"lucene\"},\"label\":\"400s\"},{\"input\":{\"query\":\"http.response.status_code:[500 TO 599]\",\"language\":\"lucene\"},\"label\":\"500s\"},{\"input\":{\"query\":\"http.response.status_code:0\",\"language\":\"lucene\"},\"label\":\"0\"}]},\"schema\":\"group\"}],\"params\":{\"type\":\"histogram\",\"grid\":{\"categoryLines\":false},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"filter\":true,\"truncate\":100},\"title\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Count\"}}],\"seriesParams\":[{\"show\":true,\"type\":\"histogram\",\"mode\":\"stacked\",\"data\":{\"label\":\"Count\",\"id\":\"1\"},\"valueAxis\":\"ValueAxis-1\",\"drawLinesBetweenPoints\":true,\"lineWidth\":2,\"showCircles\":true}],\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"times\":[],\"addTimeMarker\":false,\"labels\":{\"show\":false},\"thresholdLine\":{\"show\":false,\"value\":10,\"width\":1,\"style\":\"full\",\"color\":\"#E7664C\"}}}"},"id":"3b49a65d-54d8-483d-a8f0-3d7c855e1ecf","migrationVersion":{"visualization":"7.10.0"},"references":[{"id":"d80e05b2-518c-4c3d-9651-4c9d8632dce4","name":"search_0","type":"search"}],"type":"visualization","updated_at":"2023-04-10T22:57:51.792Z","version":"WzMsMV0="} +{"attributes":{"columns":["_source"],"description":"","hits":0,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\n \"highlightAll\": true,\n \"query\": {\n \"query\": \"http.response.status_code >= 300 and event.domain:nginx.access\",\n \"language\": \"kuery\"\n },\n \"version\": true,\n \"highlight\": {\n \"post_tags\": [\n \"@/kibana-highlighted-field@\"\n ],\n \"fields\": {\n \"*\": {}\n },\n \"pre_tags\": [\n \"@kibana-highlighted-field@\"\n ],\n \"require_field_match\": false,\n \"fragment_size\": 2147483647\n },\n \"filter\": [],\n \"indexRefName\": \"kibanaSavedObjectMeta.searchSourceJSON.index\"\n}"},"sort":[["@timestamp","desc"]],"title":"[Http Logs 1.0] Nginx Error Logs","version":1},"id":"9f820fbe-ddde-43a2-9402-30bd295c97f6","migrationVersion":{"search":"7.9.3"},"references":[{"id":"47892350-b495-11ed-af0a-cf5c93b5a3b6","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"type":"search","updated_at":"2023-04-10T22:57:51.792Z","version":"WzQsMV0="} +{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[]}"},"savedSearchRefName":"search_0","title":"[Http Logs 1.0] Errors over time","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"[Http Logs 1.0] Errors over time\",\"type\":\"histogram\",\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"params\":{},\"schema\":\"metric\"},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"params\":{\"field\":\"@timestamp\",\"timeRange\":{\"from\":\"now-15m\",\"to\":\"now\"},\"useNormalizedOpenSearchInterval\":true,\"scaleMetricValues\":false,\"interval\":\"auto\",\"drop_partials\":false,\"min_doc_count\":1,\"extended_bounds\":{}},\"schema\":\"segment\"}],\"params\":{\"type\":\"histogram\",\"grid\":{\"categoryLines\":false},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"filter\":true,\"truncate\":100},\"title\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Count\"}}],\"seriesParams\":[{\"show\":true,\"type\":\"histogram\",\"mode\":\"stacked\",\"data\":{\"label\":\"Count\",\"id\":\"1\"},\"valueAxis\":\"ValueAxis-1\",\"drawLinesBetweenPoints\":true,\"lineWidth\":2,\"showCircles\":true}],\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"times\":[],\"addTimeMarker\":false,\"labels\":{\"show\":false},\"thresholdLine\":{\"show\":false,\"value\":10,\"width\":1,\"style\":\"full\",\"color\":\"#E7664C\"}}}"},"id":"865e577b-634b-4a65-b9d6-7e324c395d18","migrationVersion":{"visualization":"7.10.0"},"references":[{"id":"9f820fbe-ddde-43a2-9402-30bd295c97f6","name":"search_0","type":"search"}],"type":"visualization","updated_at":"2023-04-10T23:06:46.320Z","version":"WzEyLDFd"} +{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}"},"savedSearchRefName":"search_0","title":"Top Paths","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"Top Paths\",\"type\":\"table\",\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"params\":{},\"schema\":\"metric\"},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"params\":{\"field\":\"http.url.keyword\",\"orderBy\":\"1\",\"order\":\"desc\",\"size\":10,\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\"},\"schema\":\"bucket\"}],\"params\":{\"perPage\":10,\"showPartialRows\":false,\"showMetricsAtAllLevels\":false,\"showTotal\":false,\"totalFunc\":\"sum\",\"percentageCol\":\"\"}}"},"id":"dc1803f0-b478-11ed-9063-ebe46f9ac203","migrationVersion":{"visualization":"7.10.0"},"references":[{"id":"d80e05b2-518c-4c3d-9651-4c9d8632dce4","name":"search_0","type":"search"}],"type":"visualization","updated_at":"2023-04-10T23:18:14.094Z","version":"WzE1LDFd"} {"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}"},"savedSearchRefName":"search_0","title":"Data Volume","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"Data Volume\",\"type\":\"area\",\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"sum\",\"params\":{\"field\":\"http.response.bytes\",\"customLabel\":\"Response Bytes\"},\"schema\":\"metric\"},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"params\":{\"field\":\"observerTime\",\"timeRange\":{\"from\":\"now-15m\",\"to\":\"now\"},\"useNormalizedOpenSearchInterval\":true,\"scaleMetricValues\":false,\"interval\":\"auto\",\"drop_partials\":false,\"min_doc_count\":1,\"extended_bounds\":{},\"customLabel\":\"\"},\"schema\":\"segment\"}],\"params\":{\"type\":\"area\",\"grid\":{\"categoryLines\":false},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"filter\":true,\"truncate\":100},\"title\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Response Bytes\"}}],\"seriesParams\":[{\"show\":true,\"type\":\"area\",\"mode\":\"stacked\",\"data\":{\"label\":\"Response Bytes\",\"id\":\"1\"},\"drawLinesBetweenPoints\":true,\"lineWidth\":2,\"showCircles\":true,\"interpolate\":\"linear\",\"valueAxis\":\"ValueAxis-1\"}],\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"times\":[],\"addTimeMarker\":false,\"thresholdLine\":{\"show\":false,\"value\":10,\"width\":1,\"style\":\"full\",\"color\":\"#E7664C\"},\"labels\":{}}}"},"id":"99acc580-b47a-11ed-9063-ebe46f9ac203","migrationVersion":{"visualization":"7.10.0"},"references":[{"id":"d80e05b2-518c-4c3d-9651-4c9d8632dce4","name":"search_0","type":"search"}],"type":"visualization","updated_at":"2023-04-10T22:57:51.792Z","version":"WzcsMV0="} {"attributes":{"description":"requests per minute aggregation","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"title":"Req-per-min","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"Req-per-min\",\"type\":\"table\",\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"moving_avg\",\"params\":{\"metricAgg\":\"custom\",\"customMetric\":{\"id\":\"1-metric\",\"enabled\":true,\"type\":\"count\",\"params\":{}},\"window\":5,\"script\":\"MovingFunctions.unweightedAvg(values)\",\"customLabel\":\"Requests (Moving Avg.)\"},\"schema\":\"metric\"},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"params\":{\"field\":\"@timestamp\",\"timeRange\":{\"from\":\"now-15m\",\"to\":\"now\"},\"useNormalizedOpenSearchInterval\":true,\"scaleMetricValues\":false,\"interval\":\"m\",\"drop_partials\":false,\"min_doc_count\":0,\"extended_bounds\":{},\"customLabel\":\"Req/Min\"},\"schema\":\"bucket\"}],\"params\":{\"perPage\":10,\"showPartialRows\":false,\"showMetricsAtAllLevels\":false,\"showTotal\":false,\"totalFunc\":\"sum\",\"percentageCol\":\"\"}}"},"id":"01ea64d0-b62f-11ed-a677-43d7aa86763b","migrationVersion":{"visualization":"7.10.0"},"references":[{"id":"47892350-b495-11ed-af0a-cf5c93b5a3b6","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"type":"visualization","updated_at":"2023-04-10T23:10:20.969Z","version":"WzEzLDFd"} {"attributes":{"description":"Basic template for HTTP-based observability dashboards","hits":0,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[]}"},"optionsJSON":"{\"hidePanelTitles\":false,\"useMargins\":true}","panelsJSON":"[{\"embeddableConfig\":{\"hidePanelTitles\":false,\"title\":\"[HTTP Logs 1.0] Response codes over time\"},\"gridData\":{\"h\":8,\"i\":\"1f31e50b-06e3-41e6-972e-e4e5fe1a9872\",\"w\":48,\"x\":0,\"y\":0},\"panelIndex\":\"1f31e50b-06e3-41e6-972e-e4e5fe1a9872\",\"title\":\"[HTTP Logs 1.0] Response codes over time\",\"version\":\"2.5.0\",\"panelRefName\":\"panel_0\"},{\"embeddableConfig\":{\"hidePanelTitles\":false,\"title\":\"[HTTP Logs 1.0] Errors over time\"},\"gridData\":{\"h\":9,\"i\":\"d91a8da4-b34b-470a-aca6-9c76b47cd6fb\",\"w\":24,\"x\":0,\"y\":8},\"panelIndex\":\"d91a8da4-b34b-470a-aca6-9c76b47cd6fb\",\"title\":\"[HTTP Logs 1.0] Errors over time\",\"version\":\"2.5.0\",\"panelRefName\":\"panel_1\"},{\"embeddableConfig\":{\"hidePanelTitles\":false,\"title\":\"[HTTP Logs 1.0] Top Paths\"},\"gridData\":{\"h\":15,\"i\":\"27149e5a-3a77-4f3c-800e-8a160c3765f4\",\"w\":24,\"x\":24,\"y\":8},\"panelIndex\":\"27149e5a-3a77-4f3c-800e-8a160c3765f4\",\"title\":\"[HTTP Logs 1.0] Top Paths\",\"version\":\"2.5.0\",\"panelRefName\":\"panel_2\"},{\"embeddableConfig\":{\"hidePanelTitles\":false,\"title\":\"[HTTP Logs 1.0] Data Volume\"},\"gridData\":{\"h\":15,\"i\":\"4d8c2aa7-159c-4a1a-80ff-00a9299056ce\",\"w\":24,\"x\":0,\"y\":17},\"panelIndex\":\"4d8c2aa7-159c-4a1a-80ff-00a9299056ce\",\"title\":\"[HTTP Logs 1.0] Data Volume\",\"version\":\"2.5.0\",\"panelRefName\":\"panel_3\"},{\"embeddableConfig\":{\"hidePanelTitles\":false,\"title\":\"[HTTP Logs 1.0] Requests per Minute\"},\"gridData\":{\"h\":15,\"i\":\"800b7f19-f50c-417f-8987-21b930531cbe\",\"w\":24,\"x\":24,\"y\":23},\"panelIndex\":\"800b7f19-f50c-417f-8987-21b930531cbe\",\"title\":\"[HTTP Logs 1.0] Requests per Minute\",\"version\":\"2.5.0\",\"panelRefName\":\"panel_4\"}]","refreshInterval":{"pause":true,"value":0},"timeFrom":"now-15m","timeRestore":true,"timeTo":"now","title":"[HTTP Logs 1.0] Overview","version":1},"id":"96847220-5261-44d0-89b4-65f3a659f13a","migrationVersion":{"dashboard":"7.9.3"},"references":[{"id":"3b49a65d-54d8-483d-a8f0-3d7c855e1ecf","name":"panel_0","type":"visualization"},{"id":"865e577b-634b-4a65-b9d6-7e324c395d18","name":"panel_1","type":"visualization"},{"id":"dc1803f0-b478-11ed-9063-ebe46f9ac203","name":"panel_2","type":"visualization"},{"id":"99acc580-b47a-11ed-9063-ebe46f9ac203","name":"panel_3","type":"visualization"},{"id":"01ea64d0-b62f-11ed-a677-43d7aa86763b","name":"panel_4","type":"visualization"}],"type":"dashboard","updated_at":"2023-04-10T23:19:07.325Z","version":"WzE2LDFd"} diff --git a/scripts/integrations-cli/upload.sh b/scripts/integrations-cli/upload.sh new file mode 100644 index 000000000..216f461c8 --- /dev/null +++ b/scripts/integrations-cli/upload.sh @@ -0,0 +1,13 @@ +# Demo script for uploading a generated integration to OSD + +echo "Loading nginx integration" + +curl -XPUT localhost:9200/_component_template/http_template -H "Content-Type: application/json" --data-binary "@integrations/nginx/schema/http.mapping" +curl -XPUT localhost:9200/_component_template/communication_template -H "Content-Type: application/json" --data-binary "@integrations/nginx/schema/communication.mapping" +curl -XPUT localhost:9200/_index_template/logs -H "Content-Type: application/json" --data-binary "@integrations/nginx/schema/communication.mapping" +curl -XPOST localhost:5601/api/saved_objects/index-pattern/sso_logs -H 'osd-xsrf: true' -H 'Content-Type: application/json' -d '{ "attributes": { "title": "sso_logs-*-*", "timeFieldName": "@timestamp" } }' +curl -XPOST "localhost:5601/api/saved_objects/_import?overwrite=true" -H "osd-xsrf: true" --form file=@integrations/nginx/assets/display/http.ndjson +# Clean messy index based on nginx startup data +curl -XDELETE "localhost:9200/sso_logs-nginx-prod" + +echo "\nLoaded" From f3dfc4cd5666067c3d46e49103f2da61742fcd10 Mon Sep 17 00:00:00 2001 From: Simeon Widdis Date: Tue, 11 Apr 2023 13:55:35 -0700 Subject: [PATCH 20/40] Fix update.sh Signed-off-by: Simeon Widdis --- scripts/integrations-cli/upload.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/integrations-cli/upload.sh b/scripts/integrations-cli/upload.sh index 216f461c8..9d9c931e6 100644 --- a/scripts/integrations-cli/upload.sh +++ b/scripts/integrations-cli/upload.sh @@ -4,7 +4,7 @@ echo "Loading nginx integration" curl -XPUT localhost:9200/_component_template/http_template -H "Content-Type: application/json" --data-binary "@integrations/nginx/schema/http.mapping" curl -XPUT localhost:9200/_component_template/communication_template -H "Content-Type: application/json" --data-binary "@integrations/nginx/schema/communication.mapping" -curl -XPUT localhost:9200/_index_template/logs -H "Content-Type: application/json" --data-binary "@integrations/nginx/schema/communication.mapping" +curl -XPUT localhost:9200/_index_template/logs -H "Content-Type: application/json" --data-binary "@integrations/nginx/schema/logs.mapping" curl -XPOST localhost:5601/api/saved_objects/index-pattern/sso_logs -H 'osd-xsrf: true' -H 'Content-Type: application/json' -d '{ "attributes": { "title": "sso_logs-*-*", "timeFieldName": "@timestamp" } }' curl -XPOST "localhost:5601/api/saved_objects/_import?overwrite=true" -H "osd-xsrf: true" --form file=@integrations/nginx/assets/display/http.ndjson # Clean messy index based on nginx startup data From 6e4ea436bd7d87a679d931a52a747cd6cd136cf9 Mon Sep 17 00:00:00 2001 From: Simeon Widdis Date: Tue, 11 Apr 2023 14:13:58 -0700 Subject: [PATCH 21/40] Fix broken dashboard Signed-off-by: Simeon Widdis --- scripts/integrations-cli/template-dashboards/http.ndjson | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/integrations-cli/template-dashboards/http.ndjson b/scripts/integrations-cli/template-dashboards/http.ndjson index 1c168fbe2..fdc50f7db 100644 --- a/scripts/integrations-cli/template-dashboards/http.ndjson +++ b/scripts/integrations-cli/template-dashboards/http.ndjson @@ -1,4 +1,4 @@ -{"attributes":{"fields":"[{\"count\":0,\"name\":\"@timestamp\",\"type\":\"date\",\"esTypes\":[\"date\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"_id\",\"type\":\"string\",\"esTypes\":[\"_id\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"count\":0,\"name\":\"_index\",\"type\":\"string\",\"esTypes\":[\"_index\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"count\":0,\"name\":\"_score\",\"type\":\"number\",\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"_source\",\"type\":\"_source\",\"esTypes\":[\"_source\"],\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"_type\",\"type\":\"string\",\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"attributes.data_stream.dataset\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"attributes.data_stream.dataset.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"attributes.data_stream.dataset\"}}},{\"count\":0,\"name\":\"attributes.data_stream.namespace\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"attributes.data_stream.namespace.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"attributes.data_stream.namespace\"}}},{\"count\":0,\"name\":\"attributes.data_stream.type\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"attributes.data_stream.type.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"attributes.data_stream.type\"}}},{\"count\":0,\"name\":\"body\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"body.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"body\"}}},{\"count\":0,\"name\":\"communication.source.address\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"communication.source.address.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"communication.source.address\"}}},{\"count\":0,\"name\":\"communication.source.ip\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"communication.source.ip.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"communication.source.ip\"}}},{\"count\":0,\"name\":\"event.category\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"event.category.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"event.category\"}}},{\"count\":0,\"name\":\"event.domain\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"event.domain.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"event.domain\"}}},{\"count\":0,\"name\":\"event.kind\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"event.kind.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"event.kind\"}}},{\"count\":0,\"name\":\"event.name\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"event.name.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"event.name\"}}},{\"count\":0,\"name\":\"event.result\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"event.result.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"event.result\"}}},{\"count\":0,\"name\":\"event.type\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"event.type.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"event.type\"}}},{\"count\":0,\"name\":\"http.flavor\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"http.flavor.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"http.flavor\"}}},{\"count\":0,\"name\":\"http.request.method\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"http.request.method.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"http.request.method\"}}},{\"count\":0,\"name\":\"http.response.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"http.response.status_code\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"http.response.status_code.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"http.response.status_code\"}}},{\"count\":0,\"name\":\"http.url\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"http.url.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"http.url\"}}},{\"count\":0,\"name\":\"observerTime\",\"type\":\"date\",\"esTypes\":[\"date\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"span_id\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"span_id.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"span_id\"}}},{\"count\":0,\"name\":\"trace_id\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"trace_id.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"trace_id\"}}}]","timeFieldName":"@timestamp","title":"sso_logs-*-*"},"id":"sso_logs","migrationVersion":{"index-pattern":"7.6.0"},"references":[],"type":"index-pattern","updated_at":"2023-04-10T23:58:51.826Z","version":"WzQwLDFd"} +{"attributes":{"fields":"[{\"count\":0,\"name\":\"@timestamp\",\"type\":\"date\",\"esTypes\":[\"date\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"_id\",\"type\":\"string\",\"esTypes\":[\"_id\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"count\":0,\"name\":\"_index\",\"type\":\"string\",\"esTypes\":[\"_index\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"count\":0,\"name\":\"_score\",\"type\":\"number\",\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"_source\",\"type\":\"_source\",\"esTypes\":[\"_source\"],\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"_type\",\"type\":\"string\",\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"attributes.data_stream.dataset\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"attributes.data_stream.dataset.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"attributes.data_stream.dataset\"}}},{\"count\":0,\"name\":\"attributes.data_stream.namespace\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"attributes.data_stream.namespace.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"attributes.data_stream.namespace\"}}},{\"count\":0,\"name\":\"attributes.data_stream.type\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"attributes.data_stream.type.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"attributes.data_stream.type\"}}},{\"count\":0,\"name\":\"body\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"body.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"body\"}}},{\"count\":0,\"name\":\"communication.source.address\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"communication.source.address.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"communication.source.address\"}}},{\"count\":0,\"name\":\"communication.source.ip\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"communication.source.ip.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"communication.source.ip\"}}},{\"count\":0,\"name\":\"event.category\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"event.category.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"event.category\"}}},{\"count\":0,\"name\":\"event.domain\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"event.domain.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"event.domain\"}}},{\"count\":0,\"name\":\"event.kind\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"event.kind.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"event.kind\"}}},{\"count\":0,\"name\":\"event.name\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"event.name.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"event.name\"}}},{\"count\":0,\"name\":\"event.result\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"event.result.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"event.result\"}}},{\"count\":0,\"name\":\"event.type\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"event.type.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"event.type\"}}},{\"count\":0,\"name\":\"http.flavor\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"http.flavor.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"http.flavor\"}}},{\"count\":0,\"name\":\"http.request.method\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"http.request.method.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"http.request.method\"}}},{\"count\":0,\"name\":\"http.response.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"http.response.status_code\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"http.response.status_code.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"http.response.status_code\"}}},{\"count\":0,\"name\":\"http.url\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"http.url.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"http.url\"}}},{\"count\":0,\"name\":\"observerTime\",\"type\":\"date\",\"esTypes\":[\"date\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"span_id\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"span_id.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"span_id\"}}},{\"count\":0,\"name\":\"trace_id\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"trace_id.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"trace_id\"}}}]","timeFieldName":"@timestamp","title":"sso_logs-*-*"},"id":"47892350-b495-11ed-af0a-cf5c93b5a3b6","migrationVersion":{"index-pattern":"7.6.0"},"references":[],"type":"index-pattern","updated_at":"2023-04-10T23:58:51.826Z","version":"WzQwLDFd"} {"attributes":{"columns":["http.request.method","http.response.status_code"],"description":"","hits":0,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\n \"highlightAll\": true,\n \"version\": true,\n \"query\": {\n \"query\": \"event.domain:nginx.access\",\n \"language\": \"kuery\"\n },\n \"filter\": [],\n \"indexRefName\": \"kibanaSavedObjectMeta.searchSourceJSON.index\"\n}"},"sort":[],"title":"[Http Logs 1.0] Nginx Access Logs","version":1},"id":"d80e05b2-518c-4c3d-9651-4c9d8632dce4","migrationVersion":{"search":"7.9.3"},"references":[{"id":"47892350-b495-11ed-af0a-cf5c93b5a3b6","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"type":"search","updated_at":"2023-04-10T22:57:51.792Z","version":"WzIsMV0="} {"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[]}"},"savedSearchRefName":"search_0","title":"[Http Logs 1.0] Response codes over time","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"[Http Logs 1.0] Response codes over time\",\"type\":\"histogram\",\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"params\":{},\"schema\":\"metric\"},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"params\":{\"field\":\"@timestamp\",\"timeRange\":{\"from\":\"now-24h\",\"to\":\"now\"},\"useNormalizedOpenSearchInterval\":true,\"scaleMetricValues\":false,\"interval\":\"auto\",\"drop_partials\":false,\"min_doc_count\":1,\"extended_bounds\":{}},\"schema\":\"segment\"},{\"id\":\"3\",\"enabled\":true,\"type\":\"filters\",\"params\":{\"filters\":[{\"input\":{\"query\":\"http.response.status_code:[200 TO 299]\",\"language\":\"lucene\"},\"label\":\"200s\"},{\"input\":{\"query\":\"http.response.status_code:[300 TO 399]\",\"language\":\"lucene\"},\"label\":\"300s\"},{\"input\":{\"query\":\"http.response.status_code:[400 TO 499]\",\"language\":\"lucene\"},\"label\":\"400s\"},{\"input\":{\"query\":\"http.response.status_code:[500 TO 599]\",\"language\":\"lucene\"},\"label\":\"500s\"},{\"input\":{\"query\":\"http.response.status_code:0\",\"language\":\"lucene\"},\"label\":\"0\"}]},\"schema\":\"group\"}],\"params\":{\"type\":\"histogram\",\"grid\":{\"categoryLines\":false},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"filter\":true,\"truncate\":100},\"title\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Count\"}}],\"seriesParams\":[{\"show\":true,\"type\":\"histogram\",\"mode\":\"stacked\",\"data\":{\"label\":\"Count\",\"id\":\"1\"},\"valueAxis\":\"ValueAxis-1\",\"drawLinesBetweenPoints\":true,\"lineWidth\":2,\"showCircles\":true}],\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"times\":[],\"addTimeMarker\":false,\"labels\":{\"show\":false},\"thresholdLine\":{\"show\":false,\"value\":10,\"width\":1,\"style\":\"full\",\"color\":\"#E7664C\"}}}"},"id":"3b49a65d-54d8-483d-a8f0-3d7c855e1ecf","migrationVersion":{"visualization":"7.10.0"},"references":[{"id":"d80e05b2-518c-4c3d-9651-4c9d8632dce4","name":"search_0","type":"search"}],"type":"visualization","updated_at":"2023-04-10T22:57:51.792Z","version":"WzMsMV0="} {"attributes":{"columns":["_source"],"description":"","hits":0,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\n \"highlightAll\": true,\n \"query\": {\n \"query\": \"http.response.status_code >= 300 and event.domain:nginx.access\",\n \"language\": \"kuery\"\n },\n \"version\": true,\n \"highlight\": {\n \"post_tags\": [\n \"@/kibana-highlighted-field@\"\n ],\n \"fields\": {\n \"*\": {}\n },\n \"pre_tags\": [\n \"@kibana-highlighted-field@\"\n ],\n \"require_field_match\": false,\n \"fragment_size\": 2147483647\n },\n \"filter\": [],\n \"indexRefName\": \"kibanaSavedObjectMeta.searchSourceJSON.index\"\n}"},"sort":[["@timestamp","desc"]],"title":"[Http Logs 1.0] Nginx Error Logs","version":1},"id":"9f820fbe-ddde-43a2-9402-30bd295c97f6","migrationVersion":{"search":"7.9.3"},"references":[{"id":"47892350-b495-11ed-af0a-cf5c93b5a3b6","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"type":"search","updated_at":"2023-04-10T22:57:51.792Z","version":"WzQsMV0="} From 977500129c774646555e13108bec92eb0dd4d4b7 Mon Sep 17 00:00:00 2001 From: Simeon Widdis Date: Tue, 11 Apr 2023 16:14:28 -0700 Subject: [PATCH 22/40] Switch from poetry Signed-off-by: Simeon Widdis --- scripts/integrations-cli/poetry.lock | 649 ---------------------- scripts/integrations-cli/pyproject.toml | 34 -- scripts/integrations-cli/requirements.txt | Bin 0 -> 970 bytes 3 files changed, 683 deletions(-) delete mode 100644 scripts/integrations-cli/poetry.lock delete mode 100644 scripts/integrations-cli/pyproject.toml create mode 100644 scripts/integrations-cli/requirements.txt diff --git a/scripts/integrations-cli/poetry.lock b/scripts/integrations-cli/poetry.lock deleted file mode 100644 index f599c5e81..000000000 --- a/scripts/integrations-cli/poetry.lock +++ /dev/null @@ -1,649 +0,0 @@ -# This file is automatically @generated by Poetry 1.4.1 and should not be changed by hand. - -[[package]] -name = "astroid" -version = "2.15.2" -description = "An abstract syntax tree for Python with inference support." -category = "dev" -optional = false -python-versions = ">=3.7.2" -files = [ - {file = "astroid-2.15.2-py3-none-any.whl", hash = "sha256:dea89d9f99f491c66ac9c04ebddf91e4acf8bd711722175fe6245c0725cc19bb"}, - {file = "astroid-2.15.2.tar.gz", hash = "sha256:6e61b85c891ec53b07471aec5878f4ac6446a41e590ede0f2ce095f39f7d49dd"}, -] - -[package.dependencies] -lazy-object-proxy = ">=1.4.0" -typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.11\""} -wrapt = [ - {version = ">=1.11,<2", markers = "python_version < \"3.11\""}, - {version = ">=1.14,<2", markers = "python_version >= \"3.11\""}, -] - -[[package]] -name = "attrs" -version = "22.2.0" -description = "Classes Without Boilerplate" -category = "main" -optional = false -python-versions = ">=3.6" -files = [ - {file = "attrs-22.2.0-py3-none-any.whl", hash = "sha256:29e95c7f6778868dbd49170f98f8818f78f3dc5e0e37c0b1f474e3561b240836"}, - {file = "attrs-22.2.0.tar.gz", hash = "sha256:c9227bfc2f01993c03f68db37d1d15c9690188323c067c641f1a35ca58185f99"}, -] - -[package.extras] -cov = ["attrs[tests]", "coverage-enable-subprocess", "coverage[toml] (>=5.3)"] -dev = ["attrs[docs,tests]"] -docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope.interface"] -tests = ["attrs[tests-no-zope]", "zope.interface"] -tests-no-zope = ["cloudpickle", "cloudpickle", "hypothesis", "hypothesis", "mypy (>=0.971,<0.990)", "mypy (>=0.971,<0.990)", "pympler", "pympler", "pytest (>=4.3.0)", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-mypy-plugins", "pytest-xdist[psutil]", "pytest-xdist[psutil]"] - -[[package]] -name = "black" -version = "23.3.0" -description = "The uncompromising code formatter." -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "black-23.3.0-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:0945e13506be58bf7db93ee5853243eb368ace1c08a24c65ce108986eac65915"}, - {file = "black-23.3.0-cp310-cp310-macosx_10_16_universal2.whl", hash = "sha256:67de8d0c209eb5b330cce2469503de11bca4085880d62f1628bd9972cc3366b9"}, - {file = "black-23.3.0-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:7c3eb7cea23904399866c55826b31c1f55bbcd3890ce22ff70466b907b6775c2"}, - {file = "black-23.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:32daa9783106c28815d05b724238e30718f34155653d4d6e125dc7daec8e260c"}, - {file = "black-23.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:35d1381d7a22cc5b2be2f72c7dfdae4072a3336060635718cc7e1ede24221d6c"}, - {file = "black-23.3.0-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:a8a968125d0a6a404842fa1bf0b349a568634f856aa08ffaff40ae0dfa52e7c6"}, - {file = "black-23.3.0-cp311-cp311-macosx_10_16_universal2.whl", hash = "sha256:c7ab5790333c448903c4b721b59c0d80b11fe5e9803d8703e84dcb8da56fec1b"}, - {file = "black-23.3.0-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:a6f6886c9869d4daae2d1715ce34a19bbc4b95006d20ed785ca00fa03cba312d"}, - {file = "black-23.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f3c333ea1dd6771b2d3777482429864f8e258899f6ff05826c3a4fcc5ce3f70"}, - {file = "black-23.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:11c410f71b876f961d1de77b9699ad19f939094c3a677323f43d7a29855fe326"}, - {file = "black-23.3.0-cp37-cp37m-macosx_10_16_x86_64.whl", hash = "sha256:1d06691f1eb8de91cd1b322f21e3bfc9efe0c7ca1f0e1eb1db44ea367dff656b"}, - {file = "black-23.3.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50cb33cac881766a5cd9913e10ff75b1e8eb71babf4c7104f2e9c52da1fb7de2"}, - {file = "black-23.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:e114420bf26b90d4b9daa597351337762b63039752bdf72bf361364c1aa05925"}, - {file = "black-23.3.0-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:48f9d345675bb7fbc3dd85821b12487e1b9a75242028adad0333ce36ed2a6d27"}, - {file = "black-23.3.0-cp38-cp38-macosx_10_16_universal2.whl", hash = "sha256:714290490c18fb0126baa0fca0a54ee795f7502b44177e1ce7624ba1c00f2331"}, - {file = "black-23.3.0-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:064101748afa12ad2291c2b91c960be28b817c0c7eaa35bec09cc63aa56493c5"}, - {file = "black-23.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:562bd3a70495facf56814293149e51aa1be9931567474993c7942ff7d3533961"}, - {file = "black-23.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:e198cf27888ad6f4ff331ca1c48ffc038848ea9f031a3b40ba36aced7e22f2c8"}, - {file = "black-23.3.0-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:3238f2aacf827d18d26db07524e44741233ae09a584273aa059066d644ca7b30"}, - {file = "black-23.3.0-cp39-cp39-macosx_10_16_universal2.whl", hash = "sha256:f0bd2f4a58d6666500542b26354978218a9babcdc972722f4bf90779524515f3"}, - {file = "black-23.3.0-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:92c543f6854c28a3c7f39f4d9b7694f9a6eb9d3c5e2ece488c327b6e7ea9b266"}, - {file = "black-23.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a150542a204124ed00683f0db1f5cf1c2aaaa9cc3495b7a3b5976fb136090ab"}, - {file = "black-23.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:6b39abdfb402002b8a7d030ccc85cf5afff64ee90fa4c5aebc531e3ad0175ddb"}, - {file = "black-23.3.0-py3-none-any.whl", hash = "sha256:ec751418022185b0c1bb7d7736e6933d40bbb14c14a0abcf9123d1b159f98dd4"}, - {file = "black-23.3.0.tar.gz", hash = "sha256:1c7b8d606e728a41ea1ccbd7264677e494e87cf630e399262ced92d4a8dac940"}, -] - -[package.dependencies] -click = ">=8.0.0" -mypy-extensions = ">=0.4.3" -packaging = ">=22.0" -pathspec = ">=0.9.0" -platformdirs = ">=2" -tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} - -[package.extras] -colorama = ["colorama (>=0.4.3)"] -d = ["aiohttp (>=3.7.4)"] -jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] -uvloop = ["uvloop (>=0.15.2)"] - -[[package]] -name = "certifi" -version = "2022.12.7" -description = "Python package for providing Mozilla's CA Bundle." -category = "main" -optional = false -python-versions = ">=3.6" -files = [ - {file = "certifi-2022.12.7-py3-none-any.whl", hash = "sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18"}, - {file = "certifi-2022.12.7.tar.gz", hash = "sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3"}, -] - -[[package]] -name = "charset-normalizer" -version = "3.1.0" -description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." -category = "main" -optional = false -python-versions = ">=3.7.0" -files = [ - {file = "charset-normalizer-3.1.0.tar.gz", hash = "sha256:34e0a2f9c370eb95597aae63bf85eb5e96826d81e3dcf88b8886012906f509b5"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e0ac8959c929593fee38da1c2b64ee9778733cdf03c482c9ff1d508b6b593b2b"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d7fc3fca01da18fbabe4625d64bb612b533533ed10045a2ac3dd194bfa656b60"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:04eefcee095f58eaabe6dc3cc2262f3bcd776d2c67005880894f447b3f2cb9c1"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20064ead0717cf9a73a6d1e779b23d149b53daf971169289ed2ed43a71e8d3b0"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1435ae15108b1cb6fffbcea2af3d468683b7afed0169ad718451f8db5d1aff6f"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c84132a54c750fda57729d1e2599bb598f5fa0344085dbde5003ba429a4798c0"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75f2568b4189dda1c567339b48cba4ac7384accb9c2a7ed655cd86b04055c795"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:11d3bcb7be35e7b1bba2c23beedac81ee893ac9871d0ba79effc7fc01167db6c"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:891cf9b48776b5c61c700b55a598621fdb7b1e301a550365571e9624f270c203"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:5f008525e02908b20e04707a4f704cd286d94718f48bb33edddc7d7b584dddc1"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:b06f0d3bf045158d2fb8837c5785fe9ff9b8c93358be64461a1089f5da983137"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:49919f8400b5e49e961f320c735388ee686a62327e773fa5b3ce6721f7e785ce"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:22908891a380d50738e1f978667536f6c6b526a2064156203d418f4856d6e86a"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-win32.whl", hash = "sha256:12d1a39aa6b8c6f6248bb54550efcc1c38ce0d8096a146638fd4738e42284448"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:65ed923f84a6844de5fd29726b888e58c62820e0769b76565480e1fdc3d062f8"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9a3267620866c9d17b959a84dd0bd2d45719b817245e49371ead79ed4f710d19"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6734e606355834f13445b6adc38b53c0fd45f1a56a9ba06c2058f86893ae8017"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f8303414c7b03f794347ad062c0516cee0e15f7a612abd0ce1e25caf6ceb47df"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aaf53a6cebad0eae578f062c7d462155eada9c172bd8c4d250b8c1d8eb7f916a"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3dc5b6a8ecfdc5748a7e429782598e4f17ef378e3e272eeb1340ea57c9109f41"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e1b25e3ad6c909f398df8921780d6a3d120d8c09466720226fc621605b6f92b1"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ca564606d2caafb0abe6d1b5311c2649e8071eb241b2d64e75a0d0065107e62"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b82fab78e0b1329e183a65260581de4375f619167478dddab510c6c6fb04d9b6"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bd7163182133c0c7701b25e604cf1611c0d87712e56e88e7ee5d72deab3e76b5"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:11d117e6c63e8f495412d37e7dc2e2fff09c34b2d09dbe2bee3c6229577818be"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:cf6511efa4801b9b38dc5546d7547d5b5c6ef4b081c60b23e4d941d0eba9cbeb"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:abc1185d79f47c0a7aaf7e2412a0eb2c03b724581139193d2d82b3ad8cbb00ac"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cb7b2ab0188829593b9de646545175547a70d9a6e2b63bf2cd87a0a391599324"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-win32.whl", hash = "sha256:c36bcbc0d5174a80d6cccf43a0ecaca44e81d25be4b7f90f0ed7bcfbb5a00909"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:cca4def576f47a09a943666b8f829606bcb17e2bc2d5911a46c8f8da45f56755"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0c95f12b74681e9ae127728f7e5409cbbef9cd914d5896ef238cc779b8152373"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fca62a8301b605b954ad2e9c3666f9d97f63872aa4efcae5492baca2056b74ab"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac0aa6cd53ab9a31d397f8303f92c42f534693528fafbdb997c82bae6e477ad9"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c3af8e0f07399d3176b179f2e2634c3ce9c1301379a6b8c9c9aeecd481da494f"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a5fc78f9e3f501a1614a98f7c54d3969f3ad9bba8ba3d9b438c3bc5d047dd28"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:628c985afb2c7d27a4800bfb609e03985aaecb42f955049957814e0491d4006d"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:74db0052d985cf37fa111828d0dd230776ac99c740e1a758ad99094be4f1803d"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:1e8fcdd8f672a1c4fc8d0bd3a2b576b152d2a349782d1eb0f6b8e52e9954731d"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:04afa6387e2b282cf78ff3dbce20f0cc071c12dc8f685bd40960cc68644cfea6"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:dd5653e67b149503c68c4018bf07e42eeed6b4e956b24c00ccdf93ac79cdff84"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d2686f91611f9e17f4548dbf050e75b079bbc2a82be565832bc8ea9047b61c8c"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-win32.whl", hash = "sha256:4155b51ae05ed47199dc5b2a4e62abccb274cee6b01da5b895099b61b1982974"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:322102cdf1ab682ecc7d9b1c5eed4ec59657a65e1c146a0da342b78f4112db23"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e633940f28c1e913615fd624fcdd72fdba807bf53ea6925d6a588e84e1151531"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3a06f32c9634a8705f4ca9946d667609f52cf130d5548881401f1eb2c39b1e2c"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7381c66e0561c5757ffe616af869b916c8b4e42b367ab29fedc98481d1e74e14"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3573d376454d956553c356df45bb824262c397c6e26ce43e8203c4c540ee0acb"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e89df2958e5159b811af9ff0f92614dabf4ff617c03a4c1c6ff53bf1c399e0e1"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:78cacd03e79d009d95635e7d6ff12c21eb89b894c354bd2b2ed0b4763373693b"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de5695a6f1d8340b12a5d6d4484290ee74d61e467c39ff03b39e30df62cf83a0"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1c60b9c202d00052183c9be85e5eaf18a4ada0a47d188a83c8f5c5b23252f649"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f645caaf0008bacf349875a974220f1f1da349c5dbe7c4ec93048cdc785a3326"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ea9f9c6034ea2d93d9147818f17c2a0860d41b71c38b9ce4d55f21b6f9165a11"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:80d1543d58bd3d6c271b66abf454d437a438dff01c3e62fdbcd68f2a11310d4b"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:73dc03a6a7e30b7edc5b01b601e53e7fc924b04e1835e8e407c12c037e81adbd"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6f5c2e7bc8a4bf7c426599765b1bd33217ec84023033672c1e9a8b35eaeaaaf8"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-win32.whl", hash = "sha256:12a2b561af122e3d94cdb97fe6fb2bb2b82cef0cdca131646fdb940a1eda04f0"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:3160a0fd9754aab7d47f95a6b63ab355388d890163eb03b2d2b87ab0a30cfa59"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:38e812a197bf8e71a59fe55b757a84c1f946d0ac114acafaafaf21667a7e169e"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6baf0baf0d5d265fa7944feb9f7451cc316bfe30e8df1a61b1bb08577c554f31"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8f25e17ab3039b05f762b0a55ae0b3632b2e073d9c8fc88e89aca31a6198e88f"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3747443b6a904001473370d7810aa19c3a180ccd52a7157aacc264a5ac79265e"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b116502087ce8a6b7a5f1814568ccbd0e9f6cfd99948aa59b0e241dc57cf739f"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d16fd5252f883eb074ca55cb622bc0bee49b979ae4e8639fff6ca3ff44f9f854"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21fa558996782fc226b529fdd2ed7866c2c6ec91cee82735c98a197fae39f706"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6f6c7a8a57e9405cad7485f4c9d3172ae486cfef1344b5ddd8e5239582d7355e"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ac3775e3311661d4adace3697a52ac0bab17edd166087d493b52d4f4f553f9f0"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:10c93628d7497c81686e8e5e557aafa78f230cd9e77dd0c40032ef90c18f2230"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:6f4f4668e1831850ebcc2fd0b1cd11721947b6dc7c00bf1c6bd3c929ae14f2c7"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:0be65ccf618c1e7ac9b849c315cc2e8a8751d9cfdaa43027d4f6624bd587ab7e"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:53d0a3fa5f8af98a1e261de6a3943ca631c526635eb5817a87a59d9a57ebf48f"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-win32.whl", hash = "sha256:a04f86f41a8916fe45ac5024ec477f41f886b3c435da2d4e3d2709b22ab02af1"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:830d2948a5ec37c386d3170c483063798d7879037492540f10a475e3fd6f244b"}, - {file = "charset_normalizer-3.1.0-py3-none-any.whl", hash = "sha256:3d9098b479e78c85080c98e1e35ff40b4a31d8953102bb0fd7d1b6f8a2111a3d"}, -] - -[[package]] -name = "click" -version = "8.1.3" -description = "Composable command line interface toolkit" -category = "main" -optional = false -python-versions = ">=3.7" -files = [ - {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"}, - {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "platform_system == \"Windows\""} - -[[package]] -name = "colorama" -version = "0.4.6" -description = "Cross-platform colored terminal text." -category = "main" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" -files = [ - {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, - {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, -] - -[[package]] -name = "dill" -version = "0.3.6" -description = "serialize all of python" -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "dill-0.3.6-py3-none-any.whl", hash = "sha256:a07ffd2351b8c678dfc4a856a3005f8067aea51d6ba6c700796a4d9e280f39f0"}, - {file = "dill-0.3.6.tar.gz", hash = "sha256:e5db55f3687856d8fbdab002ed78544e1c4559a130302693d839dfe8f93f2373"}, -] - -[package.extras] -graph = ["objgraph (>=1.7.2)"] - -[[package]] -name = "idna" -version = "3.4" -description = "Internationalized Domain Names in Applications (IDNA)" -category = "main" -optional = false -python-versions = ">=3.5" -files = [ - {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, - {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, -] - -[[package]] -name = "isort" -version = "5.12.0" -description = "A Python utility / library to sort Python imports." -category = "dev" -optional = false -python-versions = ">=3.8.0" -files = [ - {file = "isort-5.12.0-py3-none-any.whl", hash = "sha256:f84c2818376e66cf843d497486ea8fed8700b340f308f076c6fb1229dff318b6"}, - {file = "isort-5.12.0.tar.gz", hash = "sha256:8bef7dde241278824a6d83f44a544709b065191b95b6e50894bdc722fcba0504"}, -] - -[package.extras] -colors = ["colorama (>=0.4.3)"] -pipfile-deprecated-finder = ["pip-shims (>=0.5.2)", "pipreqs", "requirementslib"] -plugins = ["setuptools"] -requirements-deprecated-finder = ["pip-api", "pipreqs"] - -[[package]] -name = "jsonschema" -version = "4.17.3" -description = "An implementation of JSON Schema validation for Python" -category = "main" -optional = false -python-versions = ">=3.7" -files = [ - {file = "jsonschema-4.17.3-py3-none-any.whl", hash = "sha256:a870ad254da1a8ca84b6a2905cac29d265f805acc57af304784962a2aa6508f6"}, - {file = "jsonschema-4.17.3.tar.gz", hash = "sha256:0f864437ab8b6076ba6707453ef8f98a6a0d512a80e93f8abdb676f737ecb60d"}, -] - -[package.dependencies] -attrs = ">=17.4.0" -pyrsistent = ">=0.14.0,<0.17.0 || >0.17.0,<0.17.1 || >0.17.1,<0.17.2 || >0.17.2" - -[package.extras] -format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"] -format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "uri-template", "webcolors (>=1.11)"] - -[[package]] -name = "lazy-object-proxy" -version = "1.9.0" -description = "A fast and thorough lazy object proxy." -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "lazy-object-proxy-1.9.0.tar.gz", hash = "sha256:659fb5809fa4629b8a1ac5106f669cfc7bef26fbb389dda53b3e010d1ac4ebae"}, - {file = "lazy_object_proxy-1.9.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b40387277b0ed2d0602b8293b94d7257e17d1479e257b4de114ea11a8cb7f2d7"}, - {file = "lazy_object_proxy-1.9.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8c6cfb338b133fbdbc5cfaa10fe3c6aeea827db80c978dbd13bc9dd8526b7d4"}, - {file = "lazy_object_proxy-1.9.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:721532711daa7db0d8b779b0bb0318fa87af1c10d7fe5e52ef30f8eff254d0cd"}, - {file = "lazy_object_proxy-1.9.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:66a3de4a3ec06cd8af3f61b8e1ec67614fbb7c995d02fa224813cb7afefee701"}, - {file = "lazy_object_proxy-1.9.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:1aa3de4088c89a1b69f8ec0dcc169aa725b0ff017899ac568fe44ddc1396df46"}, - {file = "lazy_object_proxy-1.9.0-cp310-cp310-win32.whl", hash = "sha256:f0705c376533ed2a9e5e97aacdbfe04cecd71e0aa84c7c0595d02ef93b6e4455"}, - {file = "lazy_object_proxy-1.9.0-cp310-cp310-win_amd64.whl", hash = "sha256:ea806fd4c37bf7e7ad82537b0757999264d5f70c45468447bb2b91afdbe73a6e"}, - {file = "lazy_object_proxy-1.9.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:946d27deaff6cf8452ed0dba83ba38839a87f4f7a9732e8f9fd4107b21e6ff07"}, - {file = "lazy_object_proxy-1.9.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79a31b086e7e68b24b99b23d57723ef7e2c6d81ed21007b6281ebcd1688acb0a"}, - {file = "lazy_object_proxy-1.9.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f699ac1c768270c9e384e4cbd268d6e67aebcfae6cd623b4d7c3bfde5a35db59"}, - {file = "lazy_object_proxy-1.9.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bfb38f9ffb53b942f2b5954e0f610f1e721ccebe9cce9025a38c8ccf4a5183a4"}, - {file = "lazy_object_proxy-1.9.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:189bbd5d41ae7a498397287c408617fe5c48633e7755287b21d741f7db2706a9"}, - {file = "lazy_object_proxy-1.9.0-cp311-cp311-win32.whl", hash = "sha256:81fc4d08b062b535d95c9ea70dbe8a335c45c04029878e62d744bdced5141586"}, - {file = "lazy_object_proxy-1.9.0-cp311-cp311-win_amd64.whl", hash = "sha256:f2457189d8257dd41ae9b434ba33298aec198e30adf2dcdaaa3a28b9994f6adb"}, - {file = "lazy_object_proxy-1.9.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:d9e25ef10a39e8afe59a5c348a4dbf29b4868ab76269f81ce1674494e2565a6e"}, - {file = "lazy_object_proxy-1.9.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cbf9b082426036e19c6924a9ce90c740a9861e2bdc27a4834fd0a910742ac1e8"}, - {file = "lazy_object_proxy-1.9.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f5fa4a61ce2438267163891961cfd5e32ec97a2c444e5b842d574251ade27d2"}, - {file = "lazy_object_proxy-1.9.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:8fa02eaab317b1e9e03f69aab1f91e120e7899b392c4fc19807a8278a07a97e8"}, - {file = "lazy_object_proxy-1.9.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e7c21c95cae3c05c14aafffe2865bbd5e377cfc1348c4f7751d9dc9a48ca4bda"}, - {file = "lazy_object_proxy-1.9.0-cp37-cp37m-win32.whl", hash = "sha256:f12ad7126ae0c98d601a7ee504c1122bcef553d1d5e0c3bfa77b16b3968d2734"}, - {file = "lazy_object_proxy-1.9.0-cp37-cp37m-win_amd64.whl", hash = "sha256:edd20c5a55acb67c7ed471fa2b5fb66cb17f61430b7a6b9c3b4a1e40293b1671"}, - {file = "lazy_object_proxy-1.9.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2d0daa332786cf3bb49e10dc6a17a52f6a8f9601b4cf5c295a4f85854d61de63"}, - {file = "lazy_object_proxy-1.9.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cd077f3d04a58e83d04b20e334f678c2b0ff9879b9375ed107d5d07ff160171"}, - {file = "lazy_object_proxy-1.9.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:660c94ea760b3ce47d1855a30984c78327500493d396eac4dfd8bd82041b22be"}, - {file = "lazy_object_proxy-1.9.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:212774e4dfa851e74d393a2370871e174d7ff0ebc980907723bb67d25c8a7c30"}, - {file = "lazy_object_proxy-1.9.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:f0117049dd1d5635bbff65444496c90e0baa48ea405125c088e93d9cf4525b11"}, - {file = "lazy_object_proxy-1.9.0-cp38-cp38-win32.whl", hash = "sha256:0a891e4e41b54fd5b8313b96399f8b0e173bbbfc03c7631f01efbe29bb0bcf82"}, - {file = "lazy_object_proxy-1.9.0-cp38-cp38-win_amd64.whl", hash = "sha256:9990d8e71b9f6488e91ad25f322898c136b008d87bf852ff65391b004da5e17b"}, - {file = "lazy_object_proxy-1.9.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9e7551208b2aded9c1447453ee366f1c4070602b3d932ace044715d89666899b"}, - {file = "lazy_object_proxy-1.9.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f83ac4d83ef0ab017683d715ed356e30dd48a93746309c8f3517e1287523ef4"}, - {file = "lazy_object_proxy-1.9.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7322c3d6f1766d4ef1e51a465f47955f1e8123caee67dd641e67d539a534d006"}, - {file = "lazy_object_proxy-1.9.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:18b78ec83edbbeb69efdc0e9c1cb41a3b1b1ed11ddd8ded602464c3fc6020494"}, - {file = "lazy_object_proxy-1.9.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:09763491ce220c0299688940f8dc2c5d05fd1f45af1e42e636b2e8b2303e4382"}, - {file = "lazy_object_proxy-1.9.0-cp39-cp39-win32.whl", hash = "sha256:9090d8e53235aa280fc9239a86ae3ea8ac58eff66a705fa6aa2ec4968b95c821"}, - {file = "lazy_object_proxy-1.9.0-cp39-cp39-win_amd64.whl", hash = "sha256:db1c1722726f47e10e0b5fdbf15ac3b8adb58c091d12b3ab713965795036985f"}, -] - -[[package]] -name = "mccabe" -version = "0.7.0" -description = "McCabe checker, plugin for flake8" -category = "dev" -optional = false -python-versions = ">=3.6" -files = [ - {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, - {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, -] - -[[package]] -name = "mypy-extensions" -version = "1.0.0" -description = "Type system extensions for programs checked with the mypy type checker." -category = "dev" -optional = false -python-versions = ">=3.5" -files = [ - {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, - {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, -] - -[[package]] -name = "packaging" -version = "23.0" -description = "Core utilities for Python packages" -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "packaging-23.0-py3-none-any.whl", hash = "sha256:714ac14496c3e68c99c29b00845f7a2b85f3bb6f1078fd9f72fd20f0570002b2"}, - {file = "packaging-23.0.tar.gz", hash = "sha256:b6ad297f8907de0fa2fe1ccbd26fdaf387f5f47c7275fedf8cce89f99446cf97"}, -] - -[[package]] -name = "pathspec" -version = "0.11.1" -description = "Utility library for gitignore style pattern matching of file paths." -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "pathspec-0.11.1-py3-none-any.whl", hash = "sha256:d8af70af76652554bd134c22b3e8a1cc46ed7d91edcdd721ef1a0c51a84a5293"}, - {file = "pathspec-0.11.1.tar.gz", hash = "sha256:2798de800fa92780e33acca925945e9a19a133b715067cf165b8866c15a31687"}, -] - -[[package]] -name = "platformdirs" -version = "3.2.0" -description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "platformdirs-3.2.0-py3-none-any.whl", hash = "sha256:ebe11c0d7a805086e99506aa331612429a72ca7cd52a1f0d277dc4adc20cb10e"}, - {file = "platformdirs-3.2.0.tar.gz", hash = "sha256:d5b638ca397f25f979350ff789db335903d7ea010ab28903f57b27e1b16c2b08"}, -] - -[package.extras] -docs = ["furo (>=2022.12.7)", "proselint (>=0.13)", "sphinx (>=6.1.3)", "sphinx-autodoc-typehints (>=1.22,!=1.23.4)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.2.2)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"] - -[[package]] -name = "pylint" -version = "2.17.2" -description = "python code static checker" -category = "dev" -optional = false -python-versions = ">=3.7.2" -files = [ - {file = "pylint-2.17.2-py3-none-any.whl", hash = "sha256:001cc91366a7df2970941d7e6bbefcbf98694e00102c1f121c531a814ddc2ea8"}, - {file = "pylint-2.17.2.tar.gz", hash = "sha256:1b647da5249e7c279118f657ca28b6aaebb299f86bf92affc632acf199f7adbb"}, -] - -[package.dependencies] -astroid = ">=2.15.2,<=2.17.0-dev0" -colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} -dill = [ - {version = ">=0.2", markers = "python_version < \"3.11\""}, - {version = ">=0.3.6", markers = "python_version >= \"3.11\""}, -] -isort = ">=4.2.5,<6" -mccabe = ">=0.6,<0.8" -platformdirs = ">=2.2.0" -tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} -tomlkit = ">=0.10.1" - -[package.extras] -spelling = ["pyenchant (>=3.2,<4.0)"] -testutils = ["gitpython (>3)"] - -[[package]] -name = "pyrsistent" -version = "0.19.3" -description = "Persistent/Functional/Immutable data structures" -category = "main" -optional = false -python-versions = ">=3.7" -files = [ - {file = "pyrsistent-0.19.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:20460ac0ea439a3e79caa1dbd560344b64ed75e85d8703943e0b66c2a6150e4a"}, - {file = "pyrsistent-0.19.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4c18264cb84b5e68e7085a43723f9e4c1fd1d935ab240ce02c0324a8e01ccb64"}, - {file = "pyrsistent-0.19.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4b774f9288dda8d425adb6544e5903f1fb6c273ab3128a355c6b972b7df39dcf"}, - {file = "pyrsistent-0.19.3-cp310-cp310-win32.whl", hash = "sha256:5a474fb80f5e0d6c9394d8db0fc19e90fa540b82ee52dba7d246a7791712f74a"}, - {file = "pyrsistent-0.19.3-cp310-cp310-win_amd64.whl", hash = "sha256:49c32f216c17148695ca0e02a5c521e28a4ee6c5089f97e34fe24163113722da"}, - {file = "pyrsistent-0.19.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f0774bf48631f3a20471dd7c5989657b639fd2d285b861237ea9e82c36a415a9"}, - {file = "pyrsistent-0.19.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3ab2204234c0ecd8b9368dbd6a53e83c3d4f3cab10ecaf6d0e772f456c442393"}, - {file = "pyrsistent-0.19.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e42296a09e83028b3476f7073fcb69ffebac0e66dbbfd1bd847d61f74db30f19"}, - {file = "pyrsistent-0.19.3-cp311-cp311-win32.whl", hash = "sha256:64220c429e42a7150f4bfd280f6f4bb2850f95956bde93c6fda1b70507af6ef3"}, - {file = "pyrsistent-0.19.3-cp311-cp311-win_amd64.whl", hash = "sha256:016ad1afadf318eb7911baa24b049909f7f3bb2c5b1ed7b6a8f21db21ea3faa8"}, - {file = "pyrsistent-0.19.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c4db1bd596fefd66b296a3d5d943c94f4fac5bcd13e99bffe2ba6a759d959a28"}, - {file = "pyrsistent-0.19.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aeda827381f5e5d65cced3024126529ddc4289d944f75e090572c77ceb19adbf"}, - {file = "pyrsistent-0.19.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:42ac0b2f44607eb92ae88609eda931a4f0dfa03038c44c772e07f43e738bcac9"}, - {file = "pyrsistent-0.19.3-cp37-cp37m-win32.whl", hash = "sha256:e8f2b814a3dc6225964fa03d8582c6e0b6650d68a232df41e3cc1b66a5d2f8d1"}, - {file = "pyrsistent-0.19.3-cp37-cp37m-win_amd64.whl", hash = "sha256:c9bb60a40a0ab9aba40a59f68214eed5a29c6274c83b2cc206a359c4a89fa41b"}, - {file = "pyrsistent-0.19.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:a2471f3f8693101975b1ff85ffd19bb7ca7dd7c38f8a81701f67d6b4f97b87d8"}, - {file = "pyrsistent-0.19.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc5d149f31706762c1f8bda2e8c4f8fead6e80312e3692619a75301d3dbb819a"}, - {file = "pyrsistent-0.19.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3311cb4237a341aa52ab8448c27e3a9931e2ee09561ad150ba94e4cfd3fc888c"}, - {file = "pyrsistent-0.19.3-cp38-cp38-win32.whl", hash = "sha256:f0e7c4b2f77593871e918be000b96c8107da48444d57005b6a6bc61fb4331b2c"}, - {file = "pyrsistent-0.19.3-cp38-cp38-win_amd64.whl", hash = "sha256:c147257a92374fde8498491f53ffa8f4822cd70c0d85037e09028e478cababb7"}, - {file = "pyrsistent-0.19.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:b735e538f74ec31378f5a1e3886a26d2ca6351106b4dfde376a26fc32a044edc"}, - {file = "pyrsistent-0.19.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99abb85579e2165bd8522f0c0138864da97847875ecbd45f3e7e2af569bfc6f2"}, - {file = "pyrsistent-0.19.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3a8cb235fa6d3fd7aae6a4f1429bbb1fec1577d978098da1252f0489937786f3"}, - {file = "pyrsistent-0.19.3-cp39-cp39-win32.whl", hash = "sha256:c74bed51f9b41c48366a286395c67f4e894374306b197e62810e0fdaf2364da2"}, - {file = "pyrsistent-0.19.3-cp39-cp39-win_amd64.whl", hash = "sha256:878433581fc23e906d947a6814336eee031a00e6defba224234169ae3d3d6a98"}, - {file = "pyrsistent-0.19.3-py3-none-any.whl", hash = "sha256:ccf0d6bd208f8111179f0c26fdf84ed7c3891982f2edaeae7422575f47e66b64"}, - {file = "pyrsistent-0.19.3.tar.gz", hash = "sha256:1a2994773706bbb4995c31a97bc94f1418314923bd1048c6d964837040376440"}, -] - -[[package]] -name = "requests" -version = "2.28.2" -description = "Python HTTP for Humans." -category = "main" -optional = false -python-versions = ">=3.7, <4" -files = [ - {file = "requests-2.28.2-py3-none-any.whl", hash = "sha256:64299f4909223da747622c030b781c0d7811e359c37124b4bd368fb8c6518baa"}, - {file = "requests-2.28.2.tar.gz", hash = "sha256:98b1b2782e3c6c4904938b84c0eb932721069dfdb9134313beff7c83c2df24bf"}, -] - -[package.dependencies] -certifi = ">=2017.4.17" -charset-normalizer = ">=2,<4" -idna = ">=2.5,<4" -urllib3 = ">=1.21.1,<1.27" - -[package.extras] -socks = ["PySocks (>=1.5.6,!=1.5.7)"] -use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] - -[[package]] -name = "returns" -version = "0.19.0" -description = "Make your functions return something meaningful, typed, and safe!" -category = "main" -optional = false -python-versions = ">=3.7,<4.0" -files = [ - {file = "returns-0.19.0-py3-none-any.whl", hash = "sha256:ae3ce9e5165d1218905291b4d5881b4e8a86ca478437bef3b0af1de8df57ec69"}, - {file = "returns-0.19.0.tar.gz", hash = "sha256:4544bb67849c1ef1bbf7823759d433a773959e5b77a8fd06d01fef6d060f2ac5"}, -] - -[package.dependencies] -typing-extensions = ">=4.0,<5.0" - -[[package]] -name = "termcolor" -version = "2.2.0" -description = "ANSI color formatting for output in terminal" -category = "main" -optional = false -python-versions = ">=3.7" -files = [ - {file = "termcolor-2.2.0-py3-none-any.whl", hash = "sha256:91ddd848e7251200eac969846cbae2dacd7d71c2871e92733289e7e3666f48e7"}, - {file = "termcolor-2.2.0.tar.gz", hash = "sha256:dfc8ac3f350788f23b2947b3e6cfa5a53b630b612e6cd8965a015a776020b99a"}, -] - -[package.extras] -tests = ["pytest", "pytest-cov"] - -[[package]] -name = "tomli" -version = "2.0.1" -description = "A lil' TOML parser" -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, - {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, -] - -[[package]] -name = "tomlkit" -version = "0.11.7" -description = "Style preserving TOML library" -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "tomlkit-0.11.7-py3-none-any.whl", hash = "sha256:5325463a7da2ef0c6bbfefb62a3dc883aebe679984709aee32a317907d0a8d3c"}, - {file = "tomlkit-0.11.7.tar.gz", hash = "sha256:f392ef70ad87a672f02519f99967d28a4d3047133e2d1df936511465fbb3791d"}, -] - -[[package]] -name = "typing-extensions" -version = "4.5.0" -description = "Backported and Experimental Type Hints for Python 3.7+" -category = "main" -optional = false -python-versions = ">=3.7" -files = [ - {file = "typing_extensions-4.5.0-py3-none-any.whl", hash = "sha256:fb33085c39dd998ac16d1431ebc293a8b3eedd00fd4a32de0ff79002c19511b4"}, - {file = "typing_extensions-4.5.0.tar.gz", hash = "sha256:5cb5f4a79139d699607b3ef622a1dedafa84e115ab0024e0d9c044a9479ca7cb"}, -] - -[[package]] -name = "urllib3" -version = "1.26.15" -description = "HTTP library with thread-safe connection pooling, file post, and more." -category = "main" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" -files = [ - {file = "urllib3-1.26.15-py2.py3-none-any.whl", hash = "sha256:aa751d169e23c7479ce47a0cb0da579e3ede798f994f5816a74e4f4500dcea42"}, - {file = "urllib3-1.26.15.tar.gz", hash = "sha256:8a388717b9476f934a21484e8c8e61875ab60644d29b9b39e11e4b9dc1c6b305"}, -] - -[package.extras] -brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"] -secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"] -socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] - -[[package]] -name = "wrapt" -version = "1.15.0" -description = "Module for decorators, wrappers and monkey patching." -category = "dev" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" -files = [ - {file = "wrapt-1.15.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:ca1cccf838cd28d5a0883b342474c630ac48cac5df0ee6eacc9c7290f76b11c1"}, - {file = "wrapt-1.15.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:e826aadda3cae59295b95343db8f3d965fb31059da7de01ee8d1c40a60398b29"}, - {file = "wrapt-1.15.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:5fc8e02f5984a55d2c653f5fea93531e9836abbd84342c1d1e17abc4a15084c2"}, - {file = "wrapt-1.15.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:96e25c8603a155559231c19c0349245eeb4ac0096fe3c1d0be5c47e075bd4f46"}, - {file = "wrapt-1.15.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:40737a081d7497efea35ab9304b829b857f21558acfc7b3272f908d33b0d9d4c"}, - {file = "wrapt-1.15.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:f87ec75864c37c4c6cb908d282e1969e79763e0d9becdfe9fe5473b7bb1e5f09"}, - {file = "wrapt-1.15.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:1286eb30261894e4c70d124d44b7fd07825340869945c79d05bda53a40caa079"}, - {file = "wrapt-1.15.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:493d389a2b63c88ad56cdc35d0fa5752daac56ca755805b1b0c530f785767d5e"}, - {file = "wrapt-1.15.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:58d7a75d731e8c63614222bcb21dd992b4ab01a399f1f09dd82af17bbfc2368a"}, - {file = "wrapt-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:21f6d9a0d5b3a207cdf7acf8e58d7d13d463e639f0c7e01d82cdb671e6cb7923"}, - {file = "wrapt-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ce42618f67741d4697684e501ef02f29e758a123aa2d669e2d964ff734ee00ee"}, - {file = "wrapt-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41d07d029dd4157ae27beab04d22b8e261eddfc6ecd64ff7000b10dc8b3a5727"}, - {file = "wrapt-1.15.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54accd4b8bc202966bafafd16e69da9d5640ff92389d33d28555c5fd4f25ccb7"}, - {file = "wrapt-1.15.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2fbfbca668dd15b744418265a9607baa970c347eefd0db6a518aaf0cfbd153c0"}, - {file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:76e9c727a874b4856d11a32fb0b389afc61ce8aaf281ada613713ddeadd1cfec"}, - {file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e20076a211cd6f9b44a6be58f7eeafa7ab5720eb796975d0c03f05b47d89eb90"}, - {file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a74d56552ddbde46c246b5b89199cb3fd182f9c346c784e1a93e4dc3f5ec9975"}, - {file = "wrapt-1.15.0-cp310-cp310-win32.whl", hash = "sha256:26458da5653aa5b3d8dc8b24192f574a58984c749401f98fff994d41d3f08da1"}, - {file = "wrapt-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:75760a47c06b5974aa5e01949bf7e66d2af4d08cb8c1d6516af5e39595397f5e"}, - {file = "wrapt-1.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ba1711cda2d30634a7e452fc79eabcadaffedf241ff206db2ee93dd2c89a60e7"}, - {file = "wrapt-1.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:56374914b132c702aa9aa9959c550004b8847148f95e1b824772d453ac204a72"}, - {file = "wrapt-1.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a89ce3fd220ff144bd9d54da333ec0de0399b52c9ac3d2ce34b569cf1a5748fb"}, - {file = "wrapt-1.15.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3bbe623731d03b186b3d6b0d6f51865bf598587c38d6f7b0be2e27414f7f214e"}, - {file = "wrapt-1.15.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3abbe948c3cbde2689370a262a8d04e32ec2dd4f27103669a45c6929bcdbfe7c"}, - {file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b67b819628e3b748fd3c2192c15fb951f549d0f47c0449af0764d7647302fda3"}, - {file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7eebcdbe3677e58dd4c0e03b4f2cfa346ed4049687d839adad68cc38bb559c92"}, - {file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:74934ebd71950e3db69960a7da29204f89624dde411afbfb3b4858c1409b1e98"}, - {file = "wrapt-1.15.0-cp311-cp311-win32.whl", hash = "sha256:bd84395aab8e4d36263cd1b9308cd504f6cf713b7d6d3ce25ea55670baec5416"}, - {file = "wrapt-1.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:a487f72a25904e2b4bbc0817ce7a8de94363bd7e79890510174da9d901c38705"}, - {file = "wrapt-1.15.0-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:4ff0d20f2e670800d3ed2b220d40984162089a6e2c9646fdb09b85e6f9a8fc29"}, - {file = "wrapt-1.15.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:9ed6aa0726b9b60911f4aed8ec5b8dd7bf3491476015819f56473ffaef8959bd"}, - {file = "wrapt-1.15.0-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:896689fddba4f23ef7c718279e42f8834041a21342d95e56922e1c10c0cc7afb"}, - {file = "wrapt-1.15.0-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:75669d77bb2c071333417617a235324a1618dba66f82a750362eccbe5b61d248"}, - {file = "wrapt-1.15.0-cp35-cp35m-win32.whl", hash = "sha256:fbec11614dba0424ca72f4e8ba3c420dba07b4a7c206c8c8e4e73f2e98f4c559"}, - {file = "wrapt-1.15.0-cp35-cp35m-win_amd64.whl", hash = "sha256:fd69666217b62fa5d7c6aa88e507493a34dec4fa20c5bd925e4bc12fce586639"}, - {file = "wrapt-1.15.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:b0724f05c396b0a4c36a3226c31648385deb6a65d8992644c12a4963c70326ba"}, - {file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bbeccb1aa40ab88cd29e6c7d8585582c99548f55f9b2581dfc5ba68c59a85752"}, - {file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:38adf7198f8f154502883242f9fe7333ab05a5b02de7d83aa2d88ea621f13364"}, - {file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:578383d740457fa790fdf85e6d346fda1416a40549fe8db08e5e9bd281c6a475"}, - {file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:a4cbb9ff5795cd66f0066bdf5947f170f5d63a9274f99bdbca02fd973adcf2a8"}, - {file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:af5bd9ccb188f6a5fdda9f1f09d9f4c86cc8a539bd48a0bfdc97723970348418"}, - {file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:b56d5519e470d3f2fe4aa7585f0632b060d532d0696c5bdfb5e8319e1d0f69a2"}, - {file = "wrapt-1.15.0-cp36-cp36m-win32.whl", hash = "sha256:77d4c1b881076c3ba173484dfa53d3582c1c8ff1f914c6461ab70c8428b796c1"}, - {file = "wrapt-1.15.0-cp36-cp36m-win_amd64.whl", hash = "sha256:077ff0d1f9d9e4ce6476c1a924a3332452c1406e59d90a2cf24aeb29eeac9420"}, - {file = "wrapt-1.15.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5c5aa28df055697d7c37d2099a7bc09f559d5053c3349b1ad0c39000e611d317"}, - {file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3a8564f283394634a7a7054b7983e47dbf39c07712d7b177b37e03f2467a024e"}, - {file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:780c82a41dc493b62fc5884fb1d3a3b81106642c5c5c78d6a0d4cbe96d62ba7e"}, - {file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e169e957c33576f47e21864cf3fc9ff47c223a4ebca8960079b8bd36cb014fd0"}, - {file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b02f21c1e2074943312d03d243ac4388319f2456576b2c6023041c4d57cd7019"}, - {file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f2e69b3ed24544b0d3dbe2c5c0ba5153ce50dcebb576fdc4696d52aa22db6034"}, - {file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d787272ed958a05b2c86311d3a4135d3c2aeea4fc655705f074130aa57d71653"}, - {file = "wrapt-1.15.0-cp37-cp37m-win32.whl", hash = "sha256:02fce1852f755f44f95af51f69d22e45080102e9d00258053b79367d07af39c0"}, - {file = "wrapt-1.15.0-cp37-cp37m-win_amd64.whl", hash = "sha256:abd52a09d03adf9c763d706df707c343293d5d106aea53483e0ec8d9e310ad5e"}, - {file = "wrapt-1.15.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cdb4f085756c96a3af04e6eca7f08b1345e94b53af8921b25c72f096e704e145"}, - {file = "wrapt-1.15.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:230ae493696a371f1dbffaad3dafbb742a4d27a0afd2b1aecebe52b740167e7f"}, - {file = "wrapt-1.15.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63424c681923b9f3bfbc5e3205aafe790904053d42ddcc08542181a30a7a51bd"}, - {file = "wrapt-1.15.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6bcbfc99f55655c3d93feb7ef3800bd5bbe963a755687cbf1f490a71fb7794b"}, - {file = "wrapt-1.15.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c99f4309f5145b93eca6e35ac1a988f0dc0a7ccf9ccdcd78d3c0adf57224e62f"}, - {file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b130fe77361d6771ecf5a219d8e0817d61b236b7d8b37cc045172e574ed219e6"}, - {file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:96177eb5645b1c6985f5c11d03fc2dbda9ad24ec0f3a46dcce91445747e15094"}, - {file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d5fe3e099cf07d0fb5a1e23d399e5d4d1ca3e6dfcbe5c8570ccff3e9208274f7"}, - {file = "wrapt-1.15.0-cp38-cp38-win32.whl", hash = "sha256:abd8f36c99512755b8456047b7be10372fca271bf1467a1caa88db991e7c421b"}, - {file = "wrapt-1.15.0-cp38-cp38-win_amd64.whl", hash = "sha256:b06fa97478a5f478fb05e1980980a7cdf2712015493b44d0c87606c1513ed5b1"}, - {file = "wrapt-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2e51de54d4fb8fb50d6ee8327f9828306a959ae394d3e01a1ba8b2f937747d86"}, - {file = "wrapt-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0970ddb69bba00670e58955f8019bec4a42d1785db3faa043c33d81de2bf843c"}, - {file = "wrapt-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76407ab327158c510f44ded207e2f76b657303e17cb7a572ffe2f5a8a48aa04d"}, - {file = "wrapt-1.15.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cd525e0e52a5ff16653a3fc9e3dd827981917d34996600bbc34c05d048ca35cc"}, - {file = "wrapt-1.15.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d37ac69edc5614b90516807de32d08cb8e7b12260a285ee330955604ed9dd29"}, - {file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:078e2a1a86544e644a68422f881c48b84fef6d18f8c7a957ffd3f2e0a74a0d4a"}, - {file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:2cf56d0e237280baed46f0b5316661da892565ff58309d4d2ed7dba763d984b8"}, - {file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7dc0713bf81287a00516ef43137273b23ee414fe41a3c14be10dd95ed98a2df9"}, - {file = "wrapt-1.15.0-cp39-cp39-win32.whl", hash = "sha256:46ed616d5fb42f98630ed70c3529541408166c22cdfd4540b88d5f21006b0eff"}, - {file = "wrapt-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:eef4d64c650f33347c1f9266fa5ae001440b232ad9b98f1f43dfe7a79435c0a6"}, - {file = "wrapt-1.15.0-py3-none-any.whl", hash = "sha256:64b1df0f83706b4ef4cfb4fb0e4c2669100fd7ecacfb59e091fad300d4e04640"}, - {file = "wrapt-1.15.0.tar.gz", hash = "sha256:d06730c6aed78cee4126234cf2d071e01b44b915e725a6cb439a879ec9754a3a"}, -] - -[metadata] -lock-version = "2.0" -python-versions = "^3.10" -content-hash = "abdfc665273077e72886ea627e7bcb2286e269d94b983741b1987f42614281f2" diff --git a/scripts/integrations-cli/pyproject.toml b/scripts/integrations-cli/pyproject.toml deleted file mode 100644 index 41500ca6e..000000000 --- a/scripts/integrations-cli/pyproject.toml +++ /dev/null @@ -1,34 +0,0 @@ -[tool.poetry] -name = "integrations-cli" -version = "0.1.0" -description = "CLI for managing OpenSearch Integrations" -authors = ["Simeon Widdis "] -license = "Apache-2.0" - -[tool.poetry.scripts] -cli = "integrations_cli.main:integrations_cli" -test = "scripts:test" -format = "scripts:format" - -[tool.isort] -profile = "black" - -[tool.pylint] -disable = "C,R" - -[tool.poetry.dependencies] -python = "^3.10" -click = "^8.1.3" -returns = "^0.19.0" -termcolor = "^2.2.0" -jsonschema = "^4.17.3" -requests = "^2.28.2" - -[tool.poetry.dev-dependencies] -black = "^23.3.0" -isort = "^5.12.0" -pylint = "^2.17.1" - -[build-system] -requires = ["poetry-core>=1.0.0"] -build-backend = "poetry.core.masonry.api" diff --git a/scripts/integrations-cli/requirements.txt b/scripts/integrations-cli/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..ed163c5eb9f576898e457de355c0a31b0c957ab5 GIT binary patch literal 970 zcmZuw+fKqz5S(WdKSk41z{`W*V#=Xnp|rIeqww+S%x(|#!H|}OnVp@TU4DNm9FZ`h zM}rMs_$hIZfEC{*ZgGQ(xERL?6|Sc+bd8pbi2Z~vi0E-NqGn~H_8T8pFIeq8^nNsz zhDpD@c|XK2T_W~nbd)h}>LrJ^*I))^+U^aIS!VBCpXf| z2R`{0FJGfnw0YMOCy_H=X1}WV^y;9?iuCRG;nU9@Ct?TloH19?{xY_w-?>k1%x^hy vp26nb;+5V0--+%*H{`D5Shv`4$BWC(O5UR~SXts< Date: Tue, 11 Apr 2023 16:44:06 -0700 Subject: [PATCH 23/40] Add helper script and update readme Signed-off-by: Simeon Widdis --- scripts/integrations-cli/README.md | 53 +++++++++++++++++++----------- scripts/integrations-cli/integ-cli | 9 +++++ 2 files changed, 43 insertions(+), 19 deletions(-) create mode 100644 scripts/integrations-cli/integ-cli diff --git a/scripts/integrations-cli/README.md b/scripts/integrations-cli/README.md index 6de04630b..1a1d52a30 100644 --- a/scripts/integrations-cli/README.md +++ b/scripts/integrations-cli/README.md @@ -11,37 +11,52 @@ The tool has three main functions: ## Installation -The project is managed with [Poetry](https://python-poetry.org/). -After installing Poetry, install dependencies: +The project requires Python 3.7 or better. +As the project is not yet a full Python package, it must be installed manually. +To manually install, create a virtual environment and install the requirements. -```sh -$ poetry install -Installing dependencies from lock file +On Unix: + +```bash +$ python3 -m venv venv +$ source ./venv/bin/activate +$ pip install -r requirements.txt ``` -## Usage +On Windows: -The CLI can be run with: +```ps1 +> python -m venv venv +> ./venv/Scripts/activate.ps1 +> pip install -r requirements.txt +``` -```sh -$ poetry run cli -Usage: cli.cmd [OPTIONS] COMMAND [ARGS]... +On Unix, the script `integ-cli` that will automatically install necessary dependencies. + +```bash +$ ./integ-cli ``` -If you don't want to prefix everything +## Usage + +On unix, the CLI is callable with the included `integ-cli` script. + +```bash +$ ./integ-cli +``` ## Development -For development, there are a few scripts to help: +Running the tests: + +```bash +$ python -m unittest +``` -```sh -$ poetry run test -... -OK +Formatting: -$ poetry run format -... -All done! +```bash +$ black . ``` ## License diff --git a/scripts/integrations-cli/integ-cli b/scripts/integrations-cli/integ-cli new file mode 100644 index 000000000..e8f3d9019 --- /dev/null +++ b/scripts/integrations-cli/integ-cli @@ -0,0 +1,9 @@ +#!/usr/bin/bash + +if [ ! -f ./venv ]; then + echo "Virtual environment not found, creating" + python3 -m venv venv + source ./venv/bin/activate + pip install -r requirements.txt + echo "Successfully installed, calling CLI" +fi From 6801fd52d82fcfb555fe1a639f3760d3bc484415 Mon Sep 17 00:00:00 2001 From: Simeon Widdis Date: Tue, 11 Apr 2023 17:04:25 -0700 Subject: [PATCH 24/40] Update readme with workflow Signed-off-by: Simeon Widdis --- scripts/integrations-cli/README.md | 85 ++++++++++++++++++++++++++++-- 1 file changed, 82 insertions(+), 3 deletions(-) diff --git a/scripts/integrations-cli/README.md b/scripts/integrations-cli/README.md index 1a1d52a30..d918f5f3b 100644 --- a/scripts/integrations-cli/README.md +++ b/scripts/integrations-cli/README.md @@ -9,6 +9,8 @@ The tool has three main functions: - `check` an integration for validity - `package` an integration to be upload to an OpenSearch Integrations instance +Further information is provided in the `Usage` section. + ## Installation The project requires Python 3.7 or better. @@ -39,12 +41,89 @@ $ ./integ-cli ## Usage -On unix, the CLI is callable with the included `integ-cli` script. +On Unix, the CLI is callable with the included `integ-cli` script. +The simplest way to start making an integration is via `create`. ```bash -$ ./integ-cli +$ ./integ-cli --help +``` + +Further development instructions are provided below. + +### What's in an Integration? + +An integration typically consists of three components: + +- A Config file +- Schemas +- Assets + +The Config file `config.json` defines parameters for the integration. +Most notably, the versions of all involved dependencies. +It also has information like a description, +which is used when presenting the integration in the catalog. + +The Schemas `/schema` are the rules for the data, and define the permitted fields and types. +During integration creation, they are provided based on the selected components. +These are typically not meant to be changed. + +The Assets `/assets` are the "heart" of the integration. +They contain the bulk of what you develop. +All developed Assets should be compatible with the provided components. +Saved Objects, such as schemas and dashboards, are saved under `/assets/display`. + +### How to Install an Integration + +First, generate a template with desired defaults. + +```bash +$ ./integ-cli create [NAME] +``` + +To begin using the integration, first load the templates in `schema`. +The loading order generally depends on dependencies, look for a `composed_of` field. +Dependencies are loaded by uploading them to a running OpenSearch cluster. +For example, to load the `http` component under an `nginx` integration: + +```bash +$ curl -XPUT localhost:9200/_component_template/http_template -H "Content-Type: application/json" --data-binary "@integrations/nginx/schema/http.mapping" +``` + +If the component contains an `index_mapping`, +then instead post it as an index template, e.g. with `logs`: + +```bash +$ curl -XPUT localhost:9200/_index_template/logs -H "Content-Type: application/json" --data-binary "@integrations/nginx/schema/logs.mapping" +``` + +Now we turn to OpenSearch Dashboards. +First is an index pattern, which defines where to find the data. +This should generally match the pattern `ss4o_*`. + +```bash +$ curl -XPOST localhost:5601/api/saved_objects/index-pattern/sso_logs -H 'osd-xsrf: true' -H 'Content-Type: application/json' -d '{ "attributes": { "title": "sso_logs-*-*", "timeFieldName": "@timestamp" } }' ``` +Finally, load the saved objects under `/assets/display`: + +```bash +curl -XPOST "localhost:5601/api/saved_objects/_import?overwrite=true" -H "osd-xsrf: true" --form file=@integrations/nginx/assets/display/http.ndjson +``` + +We are aware that this is a complicated process. +We're working on it. + +### How to Develop an Integration + +Once the saved objects have been loaded, +you can freely change the relevant dashboards within the OpenSearch Dashboards UI. +To update the Display Assets, +export the new dashboards and replace the `.ndjson` files as desired. + +If you need to add another `schema`, +add it to the `config.json` and add the mapping to the `/schema` directory. +This is also going to be automated in the future. + ## Development Running the tests: @@ -61,4 +140,4 @@ $ black . ## License -This project, like the rest of the OpenSearch projects, is licensed under the Apache 2.0 License. +This project, like the rest of the OpenSearch projects, is licensed under the [Apache 2.0 License](https://www.apache.org/licenses/LICENSE-2.0.html). From c4a482fd047e89b33b9b455306e5952bd1e3fac8 Mon Sep 17 00:00:00 2001 From: Simeon Widdis Date: Wed, 12 Apr 2023 15:28:39 -0700 Subject: [PATCH 25/40] Fix shell scripts and make upload dynamic Signed-off-by: Simeon Widdis --- scripts/integrations-cli/integ-cli | 9 +--- .../integrations-cli/integrations_cli/main.py | 2 +- scripts/integrations-cli/upload | 43 +++++++++++++++++++ scripts/integrations-cli/upload.sh | 13 ------ 4 files changed, 45 insertions(+), 22 deletions(-) create mode 100644 scripts/integrations-cli/upload delete mode 100644 scripts/integrations-cli/upload.sh diff --git a/scripts/integrations-cli/integ-cli b/scripts/integrations-cli/integ-cli index e8f3d9019..80460a679 100644 --- a/scripts/integrations-cli/integ-cli +++ b/scripts/integrations-cli/integ-cli @@ -1,9 +1,2 @@ #!/usr/bin/bash - -if [ ! -f ./venv ]; then - echo "Virtual environment not found, creating" - python3 -m venv venv - source ./venv/bin/activate - pip install -r requirements.txt - echo "Successfully installed, calling CLI" -fi +python3 integrations_cli/main.py "$@" diff --git a/scripts/integrations-cli/integrations_cli/main.py b/scripts/integrations-cli/integrations_cli/main.py index dc43bb3e6..3dd2f4137 100644 --- a/scripts/integrations-cli/integrations_cli/main.py +++ b/scripts/integrations-cli/integrations_cli/main.py @@ -8,7 +8,7 @@ from returns.result import Result from termcolor import colored -import integrations_cli.helpers as helpers +import helpers available_templates = { "http": "template-dashboards/http.ndjson" diff --git a/scripts/integrations-cli/upload b/scripts/integrations-cli/upload new file mode 100644 index 000000000..29d0ff005 --- /dev/null +++ b/scripts/integrations-cli/upload @@ -0,0 +1,43 @@ +#!/usr/bin/bash + +# Demo script for uploading a generated integration to OSD + +bash integ-cli check $1 +FILE=integrations/$1 + +echo "Loading $1 integration" + +# First upload component templates +for f in $FILE/schema/*.mapping; do + if ! grep -q "\"index_mapping\"" "$f"; then + # Get filename without extension + filename=$(basename -- "$f") + filename="${filename%.*}" + curl -XPUT "localhost:9200/_component_template/${filename}_template" -H "Content-Type: application/json" --data-binary "@$f" + echo -e "\n" + fi +done + +# Now index templates +for f in $FILE/schema/*.mapping; do + if grep -q "\"index_mapping\"" "$f"; then + # Get filename without extension + filename=$(basename -- "$f") + filename="${filename%.*}" + curl -XPUT "localhost:9200/_index_template/${filename}" -H "Content-Type: application/json" --data-binary "@$f" + echo -e "\n" + fi +done + +# Add an sso_logs index pattern +# Other categories currently not supported +curl -XPOST localhost:5601/api/saved_objects/index-pattern/sso_logs -H 'osd-xsrf: true' -H 'Content-Type: application/json' -d '{ "attributes": { "title": "sso_logs-*-*", "timeFieldName": "@timestamp" } }' +echo -e "\n" + +# Finally, upload the saved objects +for f in $FILE/assets/display/*.ndjson; do + curl -XPOST "localhost:5601/api/saved_objects/_import?overwrite=true" -H "osd-xsrf: true" --form file=@$f + echo -e "\n" +done + +echo -e "\nLoaded" diff --git a/scripts/integrations-cli/upload.sh b/scripts/integrations-cli/upload.sh deleted file mode 100644 index 9d9c931e6..000000000 --- a/scripts/integrations-cli/upload.sh +++ /dev/null @@ -1,13 +0,0 @@ -# Demo script for uploading a generated integration to OSD - -echo "Loading nginx integration" - -curl -XPUT localhost:9200/_component_template/http_template -H "Content-Type: application/json" --data-binary "@integrations/nginx/schema/http.mapping" -curl -XPUT localhost:9200/_component_template/communication_template -H "Content-Type: application/json" --data-binary "@integrations/nginx/schema/communication.mapping" -curl -XPUT localhost:9200/_index_template/logs -H "Content-Type: application/json" --data-binary "@integrations/nginx/schema/logs.mapping" -curl -XPOST localhost:5601/api/saved_objects/index-pattern/sso_logs -H 'osd-xsrf: true' -H 'Content-Type: application/json' -d '{ "attributes": { "title": "sso_logs-*-*", "timeFieldName": "@timestamp" } }' -curl -XPOST "localhost:5601/api/saved_objects/_import?overwrite=true" -H "osd-xsrf: true" --form file=@integrations/nginx/assets/display/http.ndjson -# Clean messy index based on nginx startup data -curl -XDELETE "localhost:9200/sso_logs-nginx-prod" - -echo "\nLoaded" From 082a3fc2ca2bb5cee09eae969a09b52a435420ac Mon Sep 17 00:00:00 2001 From: Simeon Widdis Date: Wed, 12 Apr 2023 15:39:04 -0700 Subject: [PATCH 26/40] Switch to Pytest Signed-off-by: Simeon Widdis --- scripts/integrations-cli/requirements.txt | Bin 970 -> 1112 bytes .../integrations-cli/tests/test_validate.py | 8 ++++---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/integrations-cli/requirements.txt b/scripts/integrations-cli/requirements.txt index ed163c5eb9f576898e457de355c0a31b0c957ab5..22fe26ab164e3ee4f4d9c88cea9e8dcc47c5aa7b 100644 GIT binary patch delta 137 zcmX@beuHC!7^7w?Lj^-JLn=c7LkUABLq0$}Q z2CGT~veLmSjDRW(KzOq{qdg;M4p3`45LQlp$S68Fjmb^2fT0p-cq&6NkOUcN4peLm K*07vOnGpb*a2sR* delta 25 hcmcb?af*F|7~^CYMv2W0j24WOuQ9o8wqllJ1ORS82bKT; diff --git a/scripts/integrations-cli/tests/test_validate.py b/scripts/integrations-cli/tests/test_validate.py index c6498a8b8..4852f490c 100644 --- a/scripts/integrations-cli/tests/test_validate.py +++ b/scripts/integrations-cli/tests/test_validate.py @@ -9,13 +9,13 @@ from integrations_cli.helpers.catalog import _load_catalog_file -class TestSchemas(unittest.TestCase): +class TestSchemas: def test_config_schema_is_valid(self): config_schema = constants.SCHEMAS["integration.schema"] jsonschema.Draft6Validator.check_schema(config_schema) -class TestConfigValidations(unittest.TestCase): +class TestConfigValidations: def test_default_config_is_valid(self): config = deepcopy(constants.DEFAULT_CONFIG) assert is_successful(validate.validate_config(config)) @@ -31,7 +31,7 @@ def test_default_with_integer_description_is_invalid(self): assert not is_successful(validate.validate_config(config)) -class TestCatalogValidations(unittest.TestCase): +class TestCatalogValidations: def test_catalog_is_valid(self): catalog = _load_catalog_file().bind_result(validate.validate_catalog) - return is_successful(catalog) + assert is_successful(catalog) From 693cc82b8ff948f98c1df6347d9fddc4e8230749 Mon Sep 17 00:00:00 2001 From: Simeon Widdis Date: Wed, 12 Apr 2023 16:56:39 -0700 Subject: [PATCH 27/40] Tweak CI Signed-off-by: Simeon Widdis --- .../{python-poetry.yml => python-ci.yml} | 16 +++++++++------- .../integrations-cli/integrations_cli/main.py | 8 ++++---- .../{http.ndjson => logs.ndjson} | 0 3 files changed, 13 insertions(+), 11 deletions(-) rename .github/workflows/{python-poetry.yml => python-ci.yml} (54%) rename scripts/integrations-cli/template-dashboards/{http.ndjson => logs.ndjson} (100%) diff --git a/.github/workflows/python-poetry.yml b/.github/workflows/python-ci.yml similarity index 54% rename from .github/workflows/python-poetry.yml rename to .github/workflows/python-ci.yml index acebc5421..2990dd2f4 100644 --- a/.github/workflows/python-poetry.yml +++ b/.github/workflows/python-ci.yml @@ -1,8 +1,8 @@ -name: Python Poetry CI +name: Python CI on: pull_request jobs: - ci: + pytest: strategy: fail-fast: false matrix: @@ -15,9 +15,11 @@ jobs: - uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} - - name: Run image - uses: abatilo/actions-poetry@v2 + - name: Install dependencies + working-directory: ./scripts/integrations-cli + run: pip install -r requirements.txt + - uses: abatilo/pytest-action@v2 + name: Run pytest + working-directory: ./scripts/integrations-cli with: - poetry-version: ${{ matrix.poetry-version }} - - name: Run Integrations CLI unit tests - run: cd scripts/integrations-cli && poetry install && poetry run python -m unittest \ No newline at end of file + job-summary: false diff --git a/scripts/integrations-cli/integrations_cli/main.py b/scripts/integrations-cli/integrations_cli/main.py index 3dd2f4137..38aadb797 100644 --- a/scripts/integrations-cli/integrations_cli/main.py +++ b/scripts/integrations-cli/integrations_cli/main.py @@ -11,7 +11,7 @@ import helpers available_templates = { - "http": "template-dashboards/http.ndjson" + "log": "template-dashboards/logs.ndjson" } @@ -25,11 +25,11 @@ def do_add_component(builder: helpers.IntegrationBuilder) -> bool: manager = helpers.CatalogManager() choices = {} for category in manager.catalog["categories"]: - click.echo(f"- Category {category['category']}") + click.echo(f"- {colored(category['category'], color='light_blue')}") for component in category["components"]: desc = component["description"] desc = desc if len(desc) < 50 else desc[:47] + "..." - click.echo(f" - {component['component']}: {desc}") + click.echo(f" - {colored(component['component'], 'light_yellow')}: {desc}") choices[component["component"]] = component component = click.prompt( "Select component", type=click.Choice(list(choices)), show_choices=False @@ -38,7 +38,7 @@ def do_add_component(builder: helpers.IntegrationBuilder) -> bool: if component in available_templates: if click.prompt( f"A pre-made template dashboard for component `{component}` was detected. Include it? (y/n)", - type=click.Choice(["y", "n"]), + type=click.Choice(["y", "n"], False), show_choices=False ) == "y": builder.with_dashboard(available_templates[component]) diff --git a/scripts/integrations-cli/template-dashboards/http.ndjson b/scripts/integrations-cli/template-dashboards/logs.ndjson similarity index 100% rename from scripts/integrations-cli/template-dashboards/http.ndjson rename to scripts/integrations-cli/template-dashboards/logs.ndjson From c1b917d1f3e56f819591e69a1345a29fe3aec4ff Mon Sep 17 00:00:00 2001 From: Simeon Widdis Date: Wed, 12 Apr 2023 17:10:54 -0700 Subject: [PATCH 28/40] Fix CI attempt Signed-off-by: Simeon Widdis --- .github/workflows/python-ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/python-ci.yml b/.github/workflows/python-ci.yml index 2990dd2f4..ec3fac2e0 100644 --- a/.github/workflows/python-ci.yml +++ b/.github/workflows/python-ci.yml @@ -1,5 +1,6 @@ name: Python CI -on: pull_request + +on: [pull_request] jobs: pytest: From 10971b35fbfd9c35f14f13b5a69ee51e05661cc8 Mon Sep 17 00:00:00 2001 From: Simeon Widdis Date: Wed, 12 Apr 2023 17:19:17 -0700 Subject: [PATCH 29/40] Use CI from SQL cli Signed-off-by: Simeon Widdis --- .github/workflows/python-ci.yml | 50 +++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/.github/workflows/python-ci.yml b/.github/workflows/python-ci.yml index ec3fac2e0..3cf1c8eb0 100644 --- a/.github/workflows/python-ci.yml +++ b/.github/workflows/python-ci.yml @@ -1,26 +1,40 @@ -name: Python CI +name: Integrations CLI Test and Build -on: [pull_request] +on: + workflow_dispatch: + pull_request: + push: + branches-ignore: + - 'dependabot/**' + paths: + - 'scripts/integrations-cli' + - '.github/workflows/python-ci.yml' jobs: - pytest: + build: + runs-on: ubuntu-latest + defaults: + run: + working-directory: ./scripts/integrations-cli strategy: - fail-fast: false matrix: - python-version: ["3.10"] - poetry-version: ["1.0"] - os: [ubuntu-18.04, macos-latest, windows-latest] - runs-on: ${{ matrix.os }} + python-version: [3.8] + opensearch-version: [ latest ] + steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 + - name: Checkout Integrations CLI + uses: actions/checkout@v3 + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} - - name: Install dependencies - working-directory: ./scripts/integrations-cli - run: pip install -r requirements.txt - - uses: abatilo/pytest-action@v2 - name: Run pytest - working-directory: ./scripts/integrations-cli - with: - job-summary: false + + - name: Install Python Dependencies + run: | + python -m pip install --upgrade pip + pip install -r requirements.txt + pip install setuptools wheel + + - name: Run Tests + run: pytest From abd06923e9bbdb706e724e77cc748f2561cbb822 Mon Sep 17 00:00:00 2001 From: Simeon Widdis Date: Wed, 12 Apr 2023 17:21:45 -0700 Subject: [PATCH 30/40] Switch to lru_cache for compatibility Signed-off-by: Simeon Widdis --- scripts/integrations-cli/integrations_cli/helpers/catalog.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/integrations-cli/integrations_cli/helpers/catalog.py b/scripts/integrations-cli/integrations_cli/helpers/catalog.py index 7b365228a..8ef6ed68c 100644 --- a/scripts/integrations-cli/integrations_cli/helpers/catalog.py +++ b/scripts/integrations-cli/integrations_cli/helpers/catalog.py @@ -1,6 +1,6 @@ import json import os -from functools import cache +from functools import lru_cache from returns.io import impure_safe @@ -15,7 +15,7 @@ def _load_catalog_file() -> dict: class CatalogManager: - @cache + @lru_cache def __init__(self): catalog = _load_catalog_file().bind_result(validate.validate_catalog) # For now just re-throw exceptions on catalog load failure From 67ef7d60bbe85fe23bb16654ed95d27ad20667bf Mon Sep 17 00:00:00 2001 From: Simeon Widdis Date: Thu, 13 Apr 2023 10:47:07 -0700 Subject: [PATCH 31/40] Add integrations to branch Signed-off-by: Simeon Widdis --- integrations/README.md | 113 + .../display/sso-logs-dashboard-new.ndjson | 10 + integrations/nginx/config.json | 42 + integrations/nginx/info/README.md | 28 + integrations/nginx/info/fluet-bit/README.md | 62 + .../nginx/info/fluet-bit/fluent-bit.conf | 20 + .../nginx/info/fluet-bit/fluentbit.png | Bin 0 -> 2444 bytes integrations/nginx/info/nginx.png | Bin 0 -> 32420 bytes integrations/nginx/samples/README.md | 8 + .../nginx/samples/preloaded/README.md | 36 + .../nginx/samples/preloaded/bulk_logs.json | 19688 ++++++++++++++++ .../samples/preloaded/docker-compose.yaml | 56 + .../samples/preloaded/img/nginx-dashboard.png | Bin 0 -> 189559 bytes .../samples/result/nginx_access-log.json | 43 + .../nginx/samples/transformed-access_log.json | 350 + .../nginx/samples/transformed-error_log.json | 148 + .../samples/transformed-metrics_log.json | 3 + integrations/nginx/schema/README.md | 35 + .../nginx/schema/fluent-bit/parsers.conf | 126 + integrations/nginx/test/.gitignore | 1 + integrations/nginx/test/README.md | 45 + integrations/nginx/test/docker-compose.yaml | 104 + integrations/nginx/test/flask-app/Dockerfile | 5 + integrations/nginx/test/flask-app/app.py | 20 + .../nginx/test/flask-app/requirements.txt | 2 + .../nginx/test/fluent-bit/fluent-bit.conf | 30 + .../nginx/test/fluent-bit/parsers.conf | 6 + integrations/nginx/test/nginx-otel/Dockerfile | 0 .../nginx/test/nginx-otel/default.conf | 8 + .../test/nginx-otel/opentelemetry_module.conf | 8 + integrations/nginx/test/run.sh | 2 + 31 files changed, 20999 insertions(+) create mode 100644 integrations/README.md create mode 100644 integrations/nginx/assets/display/sso-logs-dashboard-new.ndjson create mode 100644 integrations/nginx/config.json create mode 100644 integrations/nginx/info/README.md create mode 100644 integrations/nginx/info/fluet-bit/README.md create mode 100644 integrations/nginx/info/fluet-bit/fluent-bit.conf create mode 100644 integrations/nginx/info/fluet-bit/fluentbit.png create mode 100644 integrations/nginx/info/nginx.png create mode 100644 integrations/nginx/samples/README.md create mode 100644 integrations/nginx/samples/preloaded/README.md create mode 100644 integrations/nginx/samples/preloaded/bulk_logs.json create mode 100644 integrations/nginx/samples/preloaded/docker-compose.yaml create mode 100644 integrations/nginx/samples/preloaded/img/nginx-dashboard.png create mode 100644 integrations/nginx/samples/result/nginx_access-log.json create mode 100644 integrations/nginx/samples/transformed-access_log.json create mode 100644 integrations/nginx/samples/transformed-error_log.json create mode 100644 integrations/nginx/samples/transformed-metrics_log.json create mode 100644 integrations/nginx/schema/README.md create mode 100644 integrations/nginx/schema/fluent-bit/parsers.conf create mode 100644 integrations/nginx/test/.gitignore create mode 100644 integrations/nginx/test/README.md create mode 100644 integrations/nginx/test/docker-compose.yaml create mode 100644 integrations/nginx/test/flask-app/Dockerfile create mode 100644 integrations/nginx/test/flask-app/app.py create mode 100644 integrations/nginx/test/flask-app/requirements.txt create mode 100644 integrations/nginx/test/fluent-bit/fluent-bit.conf create mode 100644 integrations/nginx/test/fluent-bit/parsers.conf create mode 100644 integrations/nginx/test/nginx-otel/Dockerfile create mode 100644 integrations/nginx/test/nginx-otel/default.conf create mode 100644 integrations/nginx/test/nginx-otel/opentelemetry_module.conf create mode 100644 integrations/nginx/test/run.sh diff --git a/integrations/README.md b/integrations/README.md new file mode 100644 index 000000000..8916dc79b --- /dev/null +++ b/integrations/README.md @@ -0,0 +1,113 @@ +# Definitions + +## Bundle + +An OpenSearch Integration Bundle may contain the following: + - dashboards + - visualisations + - configurations +These bundle assets are designed to assist monitor of logs and metrics for a particular resource (device, network element, service ) or group of related resources, such as “Nginx”, or “System”. + +--- + +The Bundle consists of: + +* Version +* Metadata configuration file +* Dashboards and visualisations and Notebooks +* Data stream index templates used for the signal's ingestion +* Documentation & information + + +## Integration + +An integration is a type of _bundle_ defining data-streams for ingetion of a resource observed signals using logs, metrics, and traces. + +### Structure +As mentioned above, integration is a collection of elements that formulate how to observe a specific data emitting resource - in our case a telemetry data producer. + +A typical Observability Integration consists of the following parts: + +***Metadata*** + + * Observability data producer resource + * Supplement Indices (mapping & naming) + * Collection Agent Version + * Transformation schema + * Optional test harnesses repository + * Verified version and documentation + * Category & classification (logs/traces/alerts/metrics) + +***Display components*** + + * Dashboards + * Maps + * Applications + * Notebooks + * Operations Panels + * Saved PPL/SQL/DQL Queries + * Alerts + +Since the structured data has an enormous contribution to the understanding of the system behaviour - each resource will define a well-structured mapping it conforms with. + +Once input content has form and shape - it can and will be used to calculate and correlate different pieces of data. + +The next parts of this document will present **Integrations For Observability** which has a key concept of Observability schema. + +It will overview the concepts of observability, will describe the current issues customers are facing with observability and continue to elaborate on how to mitigate them using Integrations and structured schemas. + +--- + +### Creating An Integration + +```yaml + +integration-template-name + config.json + display + Application.json + Maps.json + Dashboard.json + stored-queries + Query.json + transformation-schemas + transformation.json + samples + resource.access logs + resource.error logs + resource.stats metrics + expected_results + info + documentation + images +``` + +**Definitions** + +- `config.json` defines the general configuration for the entire integration component. +- `display` this is the folder in which the actual visualization components are stored +- `queries` this is the folder in which the actual PPL queries are stored +- `schemas` this is the folder in which the schemas are stored - schema for mapping translations or index mapping. +- `samples` this folder contains sample logs and translated logs are present +- `metadata` this folder contains additional metadata definitions such as security and policies +- `info` this folder contains documentations, licences and external references + +--- + +#### Config + +`Config.json` file includes the following Integration configuration see [NginX config](nginx/config.json) + + Additional information on the config structure see [Structure](docs/Integration-structure.md) + +#### Display: + +Visualization contains the relevant visual components associated with this integration. + +The visual display component will need to be validated to the schema that it is expected to work on - this may be part of the Integration validation flow... + +#### Queries + +Queries contains specific PPL queries that precisely demonstrates some common and useful use-case . + + diff --git a/integrations/nginx/assets/display/sso-logs-dashboard-new.ndjson b/integrations/nginx/assets/display/sso-logs-dashboard-new.ndjson new file mode 100644 index 000000000..648faf0be --- /dev/null +++ b/integrations/nginx/assets/display/sso-logs-dashboard-new.ndjson @@ -0,0 +1,10 @@ +{"attributes":{"fields":"[{\"count\":0,\"name\":\"@timestamp\",\"type\":\"date\",\"esTypes\":[\"date\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"_id\",\"type\":\"string\",\"esTypes\":[\"_id\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"count\":0,\"name\":\"_index\",\"type\":\"string\",\"esTypes\":[\"_index\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"count\":0,\"name\":\"_score\",\"type\":\"number\",\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"_source\",\"type\":\"_source\",\"esTypes\":[\"_source\"],\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"_type\",\"type\":\"string\",\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"attributes.data_stream.dataset\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"attributes.data_stream.dataset.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"attributes.data_stream.dataset\"}}},{\"count\":0,\"name\":\"attributes.data_stream.namespace\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"attributes.data_stream.namespace.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"attributes.data_stream.namespace\"}}},{\"count\":0,\"name\":\"attributes.data_stream.type\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"attributes.data_stream.type.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"attributes.data_stream.type\"}}},{\"count\":0,\"name\":\"body\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"body.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"body\"}}},{\"count\":0,\"name\":\"communication.source.address\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"communication.source.address.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"communication.source.address\"}}},{\"count\":0,\"name\":\"communication.source.ip\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"communication.source.ip.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"communication.source.ip\"}}},{\"count\":0,\"name\":\"event.category\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"event.category.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"event.category\"}}},{\"count\":0,\"name\":\"event.domain\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"event.domain.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"event.domain\"}}},{\"count\":0,\"name\":\"event.kind\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"event.kind.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"event.kind\"}}},{\"count\":0,\"name\":\"event.name\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"event.name.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"event.name\"}}},{\"count\":0,\"name\":\"event.result\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"event.result.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"event.result\"}}},{\"count\":0,\"name\":\"event.type\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"event.type.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"event.type\"}}},{\"count\":0,\"name\":\"http.flavor\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"http.flavor.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"http.flavor\"}}},{\"count\":0,\"name\":\"http.request.method\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"http.request.method.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"http.request.method\"}}},{\"count\":0,\"name\":\"http.response.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"http.response.status_code\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"http.response.status_code.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"http.response.status_code\"}}},{\"count\":0,\"name\":\"http.url\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"http.url\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"http.url\"}}},{\"count\":0,\"name\":\"observerTime\",\"type\":\"date\",\"esTypes\":[\"date\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"span_id\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"span_id.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"span_id\"}}},{\"count\":0,\"name\":\"trace_id\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"trace_id.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"trace_id\"}}}]","timeFieldName":"@timestamp","title":"sso_logs-*-*"},"id":"47892350-b495-11ed-af0a-cf5c93b5a3b6","migrationVersion":{"index-pattern":"7.6.0"},"references":[],"type":"index-pattern","updated_at":"2023-02-26T00:34:36.592Z","version":"WzYxLDdd"} +{"attributes":{"columns":["http.request.method","http.response.status_code"],"description":"","hits":0,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\n \"highlightAll\": true,\n \"version\": true,\n \"query\": {\n \"query\": \"event.domain:nginx.access\",\n \"language\": \"kuery\"\n },\n \"filter\": [],\n \"indexRefName\": \"kibanaSavedObjectMeta.searchSourceJSON.index\"\n}"},"sort":[],"title":"[NGINX Core Logs 1.0] Nginx Access Logs","version":1},"id":"d80e05b2-518c-4c3d-9651-4c9d8632dce4","migrationVersion":{"search":"7.9.3"},"references":[{"id":"47892350-b495-11ed-af0a-cf5c93b5a3b6","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"type":"search","updated_at":"2023-02-26T00:34:36.592Z","version":"WzYyLDdd"} +{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[]}"},"savedSearchRefName":"search_0","title":"[NGINX Core Logs 1.0] Response codes over time","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"[NGINX Core Logs 1.0] Response codes over time\",\"type\":\"histogram\",\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"params\":{},\"schema\":\"metric\"},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"params\":{\"field\":\"@timestamp\",\"timeRange\":{\"from\":\"now-24h\",\"to\":\"now\"},\"useNormalizedOpenSearchInterval\":true,\"scaleMetricValues\":false,\"interval\":\"auto\",\"drop_partials\":false,\"min_doc_count\":1,\"extended_bounds\":{}},\"schema\":\"segment\"},{\"id\":\"3\",\"enabled\":true,\"type\":\"filters\",\"params\":{\"filters\":[{\"input\":{\"query\":\"http.response.status_code:[200 TO 299]\",\"language\":\"lucene\"},\"label\":\"200s\"},{\"input\":{\"query\":\"http.response.status_code:[300 TO 399]\",\"language\":\"lucene\"},\"label\":\"300s\"},{\"input\":{\"query\":\"http.response.status_code:[400 TO 499]\",\"language\":\"lucene\"},\"label\":\"400s\"},{\"input\":{\"query\":\"http.response.status_code:[500 TO 599]\",\"language\":\"lucene\"},\"label\":\"500s\"},{\"input\":{\"query\":\"http.response.status_code:0\",\"language\":\"lucene\"},\"label\":\"0\"}]},\"schema\":\"group\"}],\"params\":{\"type\":\"histogram\",\"grid\":{\"categoryLines\":false},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"filter\":true,\"truncate\":100},\"title\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Count\"}}],\"seriesParams\":[{\"show\":true,\"type\":\"histogram\",\"mode\":\"stacked\",\"data\":{\"label\":\"Count\",\"id\":\"1\"},\"valueAxis\":\"ValueAxis-1\",\"drawLinesBetweenPoints\":true,\"lineWidth\":2,\"showCircles\":true}],\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"times\":[],\"addTimeMarker\":false,\"labels\":{\"show\":false},\"thresholdLine\":{\"show\":false,\"value\":10,\"width\":1,\"style\":\"full\",\"color\":\"#E7664C\"}}}"},"id":"3b49a65d-54d8-483d-a8f0-3d7c855e1ecf","migrationVersion":{"visualization":"7.10.0"},"references":[{"id":"d80e05b2-518c-4c3d-9651-4c9d8632dce4","name":"search_0","type":"search"}],"type":"visualization","updated_at":"2023-02-26T00:34:36.592Z","version":"WzYzLDdd"} +{"attributes":{"columns":["_source"],"description":"","hits":0,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\n \"highlightAll\": true,\n \"query\": {\n \"query\": \"http.response.status_code >= 300 and event.domain:nginx.access\",\n \"language\": \"kuery\"\n },\n \"version\": true,\n \"highlight\": {\n \"post_tags\": [\n \"@/kibana-highlighted-field@\"\n ],\n \"fields\": {\n \"*\": {}\n },\n \"pre_tags\": [\n \"@kibana-highlighted-field@\"\n ],\n \"require_field_match\": false,\n \"fragment_size\": 2147483647\n },\n \"filter\": [],\n \"indexRefName\": \"kibanaSavedObjectMeta.searchSourceJSON.index\"\n}"},"sort":[["@timestamp","desc"]],"title":"[NGINX Core Logs 1.0] Nginx Error Logs","version":1},"id":"9f820fbe-ddde-43a2-9402-30bd295c97f6","migrationVersion":{"search":"7.9.3"},"references":[{"id":"47892350-b495-11ed-af0a-cf5c93b5a3b6","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"type":"search","updated_at":"2023-02-26T00:34:36.592Z","version":"WzY0LDdd"} +{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[]}"},"savedSearchRefName":"search_0","title":"[NGINX Core Logs 1.0] Errors over time","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"[NGINX Core Logs 1.0] Errors over time\",\"type\":\"histogram\",\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"params\":{},\"schema\":\"metric\"},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"params\":{\"field\":\"@timestamp\",\"timeRange\":{\"from\":\"now-24h\",\"to\":\"now\"},\"useNormalizedOpenSearchInterval\":true,\"scaleMetricValues\":false,\"interval\":\"auto\",\"drop_partials\":false,\"min_doc_count\":1,\"extended_bounds\":{}},\"schema\":\"segment\"}],\"params\":{\"type\":\"histogram\",\"grid\":{\"categoryLines\":false},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"filter\":true,\"truncate\":100},\"title\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Count\"}}],\"seriesParams\":[{\"show\":true,\"type\":\"histogram\",\"mode\":\"stacked\",\"data\":{\"label\":\"Count\",\"id\":\"1\"},\"valueAxis\":\"ValueAxis-1\",\"drawLinesBetweenPoints\":true,\"lineWidth\":2,\"showCircles\":true}],\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"times\":[],\"addTimeMarker\":false,\"labels\":{\"show\":false},\"thresholdLine\":{\"show\":false,\"value\":10,\"width\":1,\"style\":\"full\",\"color\":\"#E7664C\"}}}"},"id":"865e577b-634b-4a65-b9d6-7e324c395d18","migrationVersion":{"visualization":"7.10.0"},"references":[{"id":"9f820fbe-ddde-43a2-9402-30bd295c97f6","name":"search_0","type":"search"}],"type":"visualization","updated_at":"2023-02-26T00:34:36.592Z","version":"WzY1LDdd"} +{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}"},"savedSearchRefName":"search_0","title":"Top Paths","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"Top Paths\",\"type\":\"table\",\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"params\":{},\"schema\":\"metric\"},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"params\":{\"field\":\"http.url\",\"orderBy\":\"1\",\"order\":\"desc\",\"size\":10,\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\",\"customLabel\":\"Paths\"},\"schema\":\"bucket\"}],\"params\":{\"perPage\":10,\"showPartialRows\":false,\"showMetricsAtAllLevels\":false,\"showTotal\":false,\"totalFunc\":\"sum\",\"percentageCol\":\"\"}}"},"id":"dc1803f0-b478-11ed-9063-ebe46f9ac203","migrationVersion":{"visualization":"7.10.0"},"references":[{"id":"d80e05b2-518c-4c3d-9651-4c9d8632dce4","name":"search_0","type":"search"}],"type":"visualization","updated_at":"2023-02-26T00:34:36.592Z","version":"WzY2LDdd"} +{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}"},"savedSearchRefName":"search_0","title":"Data Volume","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"Data Volume\",\"type\":\"area\",\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"sum\",\"params\":{\"field\":\"http.response.bytes\",\"customLabel\":\"Response Bytes\"},\"schema\":\"metric\"},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"params\":{\"field\":\"observerTime\",\"timeRange\":{\"from\":\"now-15m\",\"to\":\"now\"},\"useNormalizedOpenSearchInterval\":true,\"scaleMetricValues\":false,\"interval\":\"auto\",\"drop_partials\":false,\"min_doc_count\":1,\"extended_bounds\":{},\"customLabel\":\"\"},\"schema\":\"segment\"}],\"params\":{\"type\":\"area\",\"grid\":{\"categoryLines\":false},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"filter\":true,\"truncate\":100},\"title\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Response Bytes\"}}],\"seriesParams\":[{\"show\":true,\"type\":\"area\",\"mode\":\"stacked\",\"data\":{\"label\":\"Response Bytes\",\"id\":\"1\"},\"drawLinesBetweenPoints\":true,\"lineWidth\":2,\"showCircles\":true,\"interpolate\":\"linear\",\"valueAxis\":\"ValueAxis-1\"}],\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"times\":[],\"addTimeMarker\":false,\"thresholdLine\":{\"show\":false,\"value\":10,\"width\":1,\"style\":\"full\",\"color\":\"#E7664C\"},\"labels\":{}}}"},"id":"99acc580-b47a-11ed-9063-ebe46f9ac203","migrationVersion":{"visualization":"7.10.0"},"references":[{"id":"d80e05b2-518c-4c3d-9651-4c9d8632dce4","name":"search_0","type":"search"}],"type":"visualization","updated_at":"2023-02-26T00:34:36.592Z","version":"WzY3LDdd"} +{"attributes":{"description":"requests per minute aggregation","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"title":"Req-per-min","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"Req-per-min\",\"type\":\"table\",\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"moving_avg\",\"params\":{\"metricAgg\":\"custom\",\"customMetric\":{\"id\":\"1-metric\",\"enabled\":true,\"type\":\"count\",\"params\":{}},\"window\":5,\"script\":\"MovingFunctions.unweightedAvg(values)\"},\"schema\":\"metric\"},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"params\":{\"field\":\"@timestamp\",\"timeRange\":{\"from\":\"2023-02-24T17:25:00.000Z\",\"to\":\"2023-02-24T17:30:00.000Z\"},\"useNormalizedOpenSearchInterval\":true,\"scaleMetricValues\":false,\"interval\":\"m\",\"drop_partials\":false,\"min_doc_count\":0,\"extended_bounds\":{},\"customLabel\":\"Req/Min\"},\"schema\":\"bucket\"}],\"params\":{\"perPage\":10,\"showPartialRows\":false,\"showMetricsAtAllLevels\":false,\"showTotal\":false,\"totalFunc\":\"sum\",\"percentageCol\":\"\"}}"},"id":"01ea64d0-b62f-11ed-a677-43d7aa86763b","migrationVersion":{"visualization":"7.10.0"},"references":[{"id":"47892350-b495-11ed-af0a-cf5c93b5a3b6","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"type":"visualization","updated_at":"2023-02-26T23:40:53.020Z","version":"WzcyLDdd"} +{"attributes":{"description":"Nginx dashboard with basic Observability on access / error logs","hits":0,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[]}"},"optionsJSON":"{\"hidePanelTitles\":false,\"useMargins\":true}","panelsJSON":"[{\"version\":\"2.5.0\",\"gridData\":{\"h\":8,\"i\":\"1f31e50b-06e3-41e6-972e-e4e5fe1a9872\",\"w\":48,\"x\":0,\"y\":0},\"panelIndex\":\"1f31e50b-06e3-41e6-972e-e4e5fe1a9872\",\"embeddableConfig\":{},\"panelRefName\":\"panel_0\"},{\"version\":\"2.5.0\",\"gridData\":{\"h\":9,\"i\":\"d91a8da4-b34b-470a-aca6-9c76b47cd6fb\",\"w\":24,\"x\":0,\"y\":8},\"panelIndex\":\"d91a8da4-b34b-470a-aca6-9c76b47cd6fb\",\"embeddableConfig\":{},\"panelRefName\":\"panel_1\"},{\"version\":\"2.5.0\",\"gridData\":{\"h\":15,\"i\":\"27149e5a-3a77-4f3c-800e-8a160c3765f4\",\"w\":24,\"x\":24,\"y\":8},\"panelIndex\":\"27149e5a-3a77-4f3c-800e-8a160c3765f4\",\"embeddableConfig\":{},\"panelRefName\":\"panel_2\"},{\"version\":\"2.5.0\",\"gridData\":{\"x\":0,\"y\":17,\"w\":24,\"h\":15,\"i\":\"4d8c2aa7-159c-4a1a-80ff-00a9299056ce\"},\"panelIndex\":\"4d8c2aa7-159c-4a1a-80ff-00a9299056ce\",\"embeddableConfig\":{},\"panelRefName\":\"panel_3\"},{\"version\":\"2.5.0\",\"gridData\":{\"x\":24,\"y\":23,\"w\":24,\"h\":15,\"i\":\"800b7f19-f50c-417f-8987-21b930531cbe\"},\"panelIndex\":\"800b7f19-f50c-417f-8987-21b930531cbe\",\"embeddableConfig\":{},\"panelRefName\":\"panel_4\"}]","timeRestore":false,"title":"[NGINX Core Logs 1.0] Overview","version":1},"id":"96847220-5261-44d0-89b4-65f3a659f13a","migrationVersion":{"dashboard":"7.9.3"},"references":[{"id":"3b49a65d-54d8-483d-a8f0-3d7c855e1ecf","name":"panel_0","type":"visualization"},{"id":"865e577b-634b-4a65-b9d6-7e324c395d18","name":"panel_1","type":"visualization"},{"id":"dc1803f0-b478-11ed-9063-ebe46f9ac203","name":"panel_2","type":"visualization"},{"id":"99acc580-b47a-11ed-9063-ebe46f9ac203","name":"panel_3","type":"visualization"},{"id":"01ea64d0-b62f-11ed-a677-43d7aa86763b","name":"panel_4","type":"visualization"}],"type":"dashboard","updated_at":"2023-02-26T23:44:09.855Z","version":"WzczLDdd"} +{"exportedCount":9,"missingRefCount":0,"missingReferences":[]} \ No newline at end of file diff --git a/integrations/nginx/config.json b/integrations/nginx/config.json new file mode 100644 index 000000000..4dc8208ba --- /dev/null +++ b/integrations/nginx/config.json @@ -0,0 +1,42 @@ +{ + "name": "nginx", + "version": { + "integ": "0.1.0", + "schema": "1.0.0", + "resource": "^1.23.0" + }, + "description": "Nginx HTTP server collector", + "identification": "instrumentationScope.attributes.identification", + "catalog": "observability", + "components": [ + "web","http" + ], + "collection":[ + { + "logs": [{ + "info": "access logs", + "input_type":"logfile", + "dataset":"nginx.access", + "labels" :["nginx","access"] + }, + { + "info": "error logs", + "input_type":"logfile", + "labels" :["nginx","error"], + "dataset":"nginx.error" + }] + }, + { + "metrics": [{ + "info": "status metrics", + "input_type":"metrics", + "dataset":"nginx.status", + "labels" :["nginx","status"] + }] + } + ], + "repo": { + "github": "https://github.com/opensearch-project/observability/tree/main/integrarions/nginx" + } +} + diff --git a/integrations/nginx/info/README.md b/integrations/nginx/info/README.md new file mode 100644 index 000000000..9daa94595 --- /dev/null +++ b/integrations/nginx/info/README.md @@ -0,0 +1,28 @@ +![](nginx.png) + +# Nginx Integrations + +## What it Nginx ? +Nginx is a popular open-source web server software used by millions of websites worldwide. It was developed to address the limitations of Apache, which is another popular web server software. Nginx is known for its high performance, scalability, and reliability, and is widely used as a reverse proxy server, load balancer, and HTTP cache. + +One of the primary advantages of Nginx is its ability to handle large numbers of concurrent connections and requests. It uses an event-driven architecture that allows it to handle multiple connections with minimal resources, making it an ideal choice for high-traffic websites. In addition, Nginx can also serve static content very efficiently, which further improves its performance. + +Another important feature of Nginx is its ability to act as a reverse proxy server. This means that it can sit in front of web servers and route incoming requests to the appropriate server based on various criteria, such as the URL or the type of request. Reverse proxying can help improve website performance and security by caching static content, load balancing incoming traffic, and providing an additional layer of protection against attacks. + +Nginx is also widely used as a load balancer. In this role, it distributes incoming traffic across multiple web servers to improve performance and ensure high availability. Nginx can balance traffic using a variety of algorithms, such as round-robin or least connections, and can also perform health checks to ensure that requests are only sent to healthy servers. + +Finally, Nginx is also an effective HTTP cache. By caching frequently accessed content, Nginx can reduce the load on backend servers and improve website performance. Nginx can cache content based on a variety of criteria, such as the URL, response headers, or response body. + +## What is An Nginx Integration ? +As described in the [documentation](../../README.md) Nginx integrations is a bundle of resources, assets and documentations. + +An Integration may have multiple ways of ingesting Observability signals, for example nginx logs may arrive via fluent-bit agent or OTEL-logs collector... + +## Which are the Nginx Observability providers ? +Observability Providers are agents which can collect nginx logs, metrics and traces information, convert them to `sso` observability schema and send them to opensearch observability data-streams. + +### Fluent-Bit +Fluent-bit has a dedicated input plugin for Nginx called `in_tail` which can be used to tail the Nginx access logs and send them to a destination of your choice. +The in_tail plugin reads log files line by line and sends them to Fluent-bit engine to be processed. + +See additional details [here](fluet-bit/README.md). \ No newline at end of file diff --git a/integrations/nginx/info/fluet-bit/README.md b/integrations/nginx/info/fluet-bit/README.md new file mode 100644 index 000000000..ea97a4835 --- /dev/null +++ b/integrations/nginx/info/fluet-bit/README.md @@ -0,0 +1,62 @@ +![](fluentbit.png) + +## Fluent-bit + +Fluent-bit is a lightweight and flexible log data collector and forwarder, designed to handle a large volume of log data in real-time. It is an open-source project maintained by Fluentd Inc. and has gained popularity among developers due to its simplicity and ease of use. + +Fluent-bit is designed to be lightweight, which means that it has a small footprint and can be installed on resource-constrained environments like embedded systems or containers. It is written in C language, making it fast and efficient, and it has a low memory footprint, which allows it to consume minimal system resources. + +Fluent-bit is a versatile tool that can collect data from various sources, including files, standard input, syslog, and TCP/UDP sockets. It also supports parsing different log formats like JSON, Apache, and Syslog. Fluent-bit provides a flexible configuration system that allows users to tailor their log collection needs, which makes it easy to adapt to different use cases. + +One of the main advantages of Fluent-bit is its ability to forward log data to various destinations, including Opensearch, InfluxDB, and Kafka. Fluent-bit provides multiple output plugins that allow users to route their log data to different destinations based on their requirements. This feature makes Fluent-bit ideal for distributed systems where log data needs to be collected and centralized in a central repository. + +Fluent-bit also provides a powerful filtering mechanism that allows users to manipulate log data in real-time. It supports various filter plugins, including record modifiers, parsers, and field extraction. With these filters, users can parse and enrich log data, extract fields, and modify records before sending them to their destination. + +## Setting Up Fluent-bit agent + +For setting up a fluent-bit agent on Nginx, please follow the next instructions + +- Install Fluent-bit on the Nginx server. You can download the latest package from the official Fluent-bit website or use your package manager to install it. + +- Once Fluent-bit is installed, create a configuration file named fluent-bit.conf in the /etc/fluent-bit/ directory. Add the following configuration to the file: + +```text +[SERVICE] + Flush 1 + Log_Level info + Parsers_File parsers.conf + +[Filter] + Name lua + Match * + code function cb_filter(a,b,c)local d={}local e=os.date("!%Y-%m-%dT%H:%M:%S.000Z")d["observerTime"]=e;d["body"]=c.remote.." "..c.host.." "..c.user.." ["..os.date("%d/%b/%Y:%H:%M:%S %z").."] \""..c.method.." "..c.path.." HTTP/1.1\" "..c.code.." "..c.size.." \""..c.referer.."\" \""..c.agent.."\""d["trace_id"]="102981ABCD2901"d["span_id"]="abcdef1010"d["attributes"]={}d["attributes"]["data_stream"]={}d["attributes"]["data_stream"]["dataset"]="nginx.access"d["attributes"]["data_stream"]["namespace"]="production"d["attributes"]["data_stream"]["type"]="logs"d["event"]={}d["event"]["category"]={"web"}d["event"]["name"]="access"d["event"]["domain"]="nginx.access"d["event"]["kind"]="event"d["event"]["result"]="success"d["event"]["type"]={"access"}d["http"]={}d["http"]["request"]={}d["http"]["request"]["method"]=c.method;d["http"]["response"]={}d["http"]["response"]["bytes"]=tonumber(c.size)d["http"]["response"]["status_code"]=c.code;d["http"]["flavor"]="1.1"d["http"]["url"]=c.path;d["communication"]={}d["communication"]["source"]={}d["communication"]["source"]["address"]="127.0.0.1"d["communication"]["source"]["ip"]=c.remote;return 1,b,d end + call cb_filter + +[INPUT] + Name tail + Path /var/log/nginx/access.log + Tag nginx.access + DB /var/log/flb_input.access.db + Mem_Buf_Limit 5MB + Skip_Long_Lines On + +[OUTPUT] + Name os + Match nginx.* + Host + Port + Index sso_nginx-access-%Y.%m.%d +``` +Here, we specify the input plugin as tail, set the path to the Nginx access log file, and specify a tag to identify the logs in Fluent-bit. We also set some additional parameters such as memory buffer limit and skipping long lines. + +For the output, we use the `os` plugin to send the logs to Opensearch. We specify the Opensearch host, port, and index name. + +- Modify the Opensearch host and port in the configuration file to match your Opensearch installation. +- Start the Fluent-bit service by running the following command: +```text +sudo systemctl start fluent-bit +``` +- Verify that Fluent-bit is running by checking its status: +```text +sudo systemctl status fluent-bit +``` \ No newline at end of file diff --git a/integrations/nginx/info/fluet-bit/fluent-bit.conf b/integrations/nginx/info/fluet-bit/fluent-bit.conf new file mode 100644 index 000000000..953893979 --- /dev/null +++ b/integrations/nginx/info/fluet-bit/fluent-bit.conf @@ -0,0 +1,20 @@ +[INPUT] + Name tail + Path /var/log/nginx/access.log + Tag nginx.access + DB /var/log/flb_input.access.db + Mem_Buf_Limit 5MB + Skip_Long_Lines On + +[Filter] + Name lua + Match * + code function cb_filter(a,b,c)local d={}local e=os.date("!%Y-%m-%dT%H:%M:%S.000Z")d["observerTime"]=e;d["body"]=c.remote.." "..c.host.." "..c.user.." ["..os.date("%d/%b/%Y:%H:%M:%S %z").."] \""..c.method.." "..c.path.." HTTP/1.1\" "..c.code.." "..c.size.." \""..c.referer.."\" \""..c.agent.."\""d["trace_id"]="102981ABCD2901"d["span_id"]="abcdef1010"d["attributes"]={}d["attributes"]["data_stream"]={}d["attributes"]["data_stream"]["dataset"]="nginx.access"d["attributes"]["data_stream"]["namespace"]="production"d["attributes"]["data_stream"]["type"]="logs"d["event"]={}d["event"]["category"]={"web"}d["event"]["name"]="access"d["event"]["domain"]="nginx.access"d["event"]["kind"]="event"d["event"]["result"]="success"d["event"]["type"]={"access"}d["http"]={}d["http"]["request"]={}d["http"]["request"]["method"]=c.method;d["http"]["response"]={}d["http"]["response"]["bytes"]=tonumber(c.size)d["http"]["response"]["status_code"]=c.code;d["http"]["flavor"]="1.1"d["http"]["url"]=c.path;d["communication"]={}d["communication"]["source"]={}d["communication"]["source"]["address"]="127.0.0.1"d["communication"]["source"]["ip"]=c.remote;return 1,b,d end + call cb_filter + +[OUTPUT] + Name os + Match nginx.* + Host + Port + Index sso_nginx-access-%Y.%m.%d diff --git a/integrations/nginx/info/fluet-bit/fluentbit.png b/integrations/nginx/info/fluet-bit/fluentbit.png new file mode 100644 index 0000000000000000000000000000000000000000..770a562a6c8029081aff03e9c6a8d73a2e85cd80 GIT binary patch literal 2444 zcmbVN`#;l-7yoQFt%=BD=AJO3FnOrdTyhNy`6{UiPc9jWnM*bv((oj?EHM^xnM*8} zAxuPJC{J`VVxr_$5n1!>`9A-_b6)3l&UwGi`@CPT^Ey8qD$dzf5{`lc03c~^XYC3A zAW;bdU}B;aTXJVEfyi3bieb}+JZgK0X7h~Z-R=xdkj{fQ`8|HVb!6oN7AlbmYJ6;x z{`_8#pGZ)o0I=Kkrc@dybeIs?X2C3@)NZE>%zbf8hq5&D;%vJ>mQ_THXH^okuJuGh zcOWaykWsjw!9)}^rFC3s?4SK56uP6PmqfdpMz}h=0XH{I_kR__qzk_($+NUR6B=#* zB4BuZHbSA-^-~C&mHhyxiLAnGRc3gP2;%$08G~2+QOamcJbbv z<@7m(O=TfPJz}40X=-9*gpxa=t_wYMeY?4(ytIHKW3d#uYx1YR9p_6<`wyL|Z~q+Q zzuAVAwA0y85LZCJwDqnYXlu^)$g2*4HW19(wm#oOz3yyR<|ikv4JP6)lyVlit-1z5 z6coE9FlQWxed7#bGAe6=;VUaT?Q2zH7$`fD=d_Gw6E%Daqkv5CU)WBEF(W7;9W}p3 z9Mj+F2}df7EEtOY%35;(FPelJcc}~mL5wkvx$65o)IqyC*UIe94+X5e;ru_a!^UCL zN3_*uKX!L_&-gw(^UB@Iw(gwyvC0sf)b6TD7fNd|(g4F4FBd-#esOO1F=1cdDk<(o ztw+^jN!Ga{j!ska1&tuS*)E>8dG4rAgcdEZCgOu%j@4 z`+az8(XS>06c#J6sIkK#t^}_da8eIzg8m zIBbwPEiZ-s@}P(}fzfc%!f!MIX{p0)6;5qCZ=HuUn70Qy-1`Pee=L-IE8N`Li(8AP zf8C7TxpGZ1-syg0*^aJ^2rNqho@^bh^t_kWQ;o7NV#N;+MTz<>q8ic=b2qPuD89MXdBwM>;b%SrD;GQtrIyCD^YEy zy*RV8v*$rHT9Gt^H_`c69nWXM`g_}Wd$4z+qC(Mk+3A3FdHs${@tr65GN3=TwWfr^ z&8HV+Ugp(#iJ?a}W^@+#KjcTEFM-(!TXS>ry?lQovv5U_@Au8}(i~p|8V#QJY3-PQd2(jeP3%XM zjbK<0H1wX>#WEv?zEIM{XsB7aBo}a>$VsO{(z{CBZ_8E$+|r5ZuQkl7&`~>mS>5$X zq@zWmN;v3~W18_&jaJNMOTZir2{q1~ z+?(6>Oh9XD@K?Fp0Nn0m^syG#0y1{6TJ`vY)ZFh%_|{BVpWN44YG_kpl52hK~) zFhRbLA7ui<+fp$`P+xd)pQ4kYkfhh&hW+R5HJ_@4G0^5~AjGp|s2W)v7<453x%Het(VtsD}mT{^n`U@T1 zzds;50A@V7RTqD3_|hS5nheJo@gRc%J-x43jF0GBQ;-MQZ%ssEmWE-t-4`x4*X&|H zx{)v>P+_H0Zo2b&uTq?mhZea#T@S_jKdoNHc?)8Tq96$Cz{cv z0_~hb-`@CQfR58^jE}d)>Z);rdx~w6yi3V@h!Q(lb#k!j6u zcbmDXf8U`W3^w{|d8cOmi3goImZ?YK-fB1`&na(;zjnX;-ROxYchoJ9A5|tm$o503F|y4AZdwY2JqR69p|>yLi7B=Xhd(8~!n}tf$9JU9BsFOG)kr9TNr9&Fk{8t}QpsauG+(Ri zkj#VoIkXS4$sbp98y9ny?sn6xC>h32$jLy_9cuk6ay8?WizU2%0}PJ4U#ybhRaC9z z`7>qIm3|aDqTs5bETt{n(!!#pH1hK?^}77UDAu7@4<3%bS!(?<6#a}hW$Ie~F~sdR kmf*ekfBVa#DWRMYde?!vUUDgW?H>{Qlg`$)miWZK0fe(s00000 literal 0 HcmV?d00001 diff --git a/integrations/nginx/info/nginx.png b/integrations/nginx/info/nginx.png new file mode 100644 index 0000000000000000000000000000000000000000..abd7803d5ac88c81295723de49b39ccd75134948 GIT binary patch literal 32420 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 z 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 literal 0 HcmV?d00001 diff --git a/integrations/nginx/samples/result/nginx_access-log.json b/integrations/nginx/samples/result/nginx_access-log.json new file mode 100644 index 000000000..8a316430b --- /dev/null +++ b/integrations/nginx/samples/result/nginx_access-log.json @@ -0,0 +1,43 @@ +{ + "@timestamp": "2022-12-09T10:39:23.000Z", + "observerTime": "2022-12-09T10:39:38.896Z", + "body": "47.29.201.179 - - [01/Mar/2020:10:34:43 +0100] \"GET / HTTP/1.1\" 200 612 \"-\" \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.119 Safari/537.36\"", + "trace_id":"102981ABCD2901", + "span_id":"abcdef1010", + "attributes": { + "data_stream": { + "dataset": "nginx.access", + "namespace": "production", + "type": "logs" + } + }, + "event": { + "category": [ + "web" + ], + "name": "access", + "domain": "nginx.access", + "kind": "event", + "result": "success", + "type": [ + "access" + ] + }, + "http": { + "request": { + "method": "GET" + }, + "response": { + "bytes": 97, + "status_code": "200" + }, + "flavor": "1.1", + "url": "/server-status" + }, + "communication": { + "source": { + "address": "127.0.0.1", + "ip": "127.0.0.1" + } + } +} \ No newline at end of file diff --git a/integrations/nginx/samples/transformed-access_log.json b/integrations/nginx/samples/transformed-access_log.json new file mode 100644 index 000000000..0e4a4ee6a --- /dev/null +++ b/integrations/nginx/samples/transformed-access_log.json @@ -0,0 +1,350 @@ +{ + "result": [ + { + "@timestamp": "2016-12-07T10:05:07.000Z", + "_tmp": {}, + "ecs": { + "version": "8.5.1" + }, + "event": { + "category": [ + "web" + ], + "created": "2020-04-28T11:07:58.223Z", + "ingested": "2022-12-09T10:33:39.725697721Z", + "kind": "event", + "original": "10.0.0.2, 10.0.0.1, 127.0.0.1 - - [07/Dec/2016:11:05:07 +0100] \"GET /ocelot HTTP/1.1\" 200 571 \"-\" \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:49.0) Gecko/20100101 Firefox/49.0\"", + "outcome": "success", + "type": [ + "access" + ] + }, + "http": { + "request": { + "method": "GET" + }, + "response": { + "body": { + "bytes": 571 + }, + "status_code": 200 + }, + "version": "1.1" + }, + "nginx": { + "access": { + "remote_ip_list": [ + "10.0.0.2", + "10.0.0.1", + "127.0.0.1" + ] + } + }, + "related": { + "ip": [ + "10.0.0.2" + ] + }, + "source": { + "address": "10.0.0.2", + "ip": "10.0.0.2" + }, + "tags": [ + "preserve_original_event" + ], + "url": { + "original": "/ocelot", + "path": "/ocelot" + }, + "user_agent": { + "device": { + "name": "Mac" + }, + "name": "Firefox", + "original": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:49.0) Gecko/20100101 Firefox/49.0", + "os": { + "full": "Mac OS X 10.12", + "name": "Mac OS X", + "version": "10.12" + }, + "version": "49.0." + } + }, + { + "@timestamp": "2017-05-29T19:02:48.000Z", + "_tmp": {}, + "ecs": { + "version": "8.5.1" + }, + "event": { + "category": [ + "web" + ], + "created": "2020-04-28T11:07:58.223Z", + "ingested": "2022-12-09T10:33:39.725715762Z", + "kind": "event", + "original": "172.17.0.1 - - [29/May/2017:19:02:48 +0000] \"GET /stringpatch HTTP/1.1\" 404 612 \"-\" \"Mozilla/5.0 (Windows NT 6.1; rv:15.0) Gecko/20120716 Firefox/15.0a2\" \"-\"", + "outcome": "failure", + "type": [ + "access" + ] + }, + "http": { + "request": { + "method": "GET" + }, + "response": { + "body": { + "bytes": 612 + }, + "status_code": 404 + }, + "version": "1.1" + }, + "nginx": { + "access": { + "remote_ip_list": [ + "172.17.0.1" + ] + } + }, + "related": { + "ip": [ + "172.17.0.1" + ] + }, + "source": { + "address": "172.17.0.1", + "ip": "172.17.0.1" + }, + "tags": [ + "preserve_original_event" + ], + "url": { + "original": "/stringpatch", + "path": "/stringpatch" + }, + "user_agent": { + "device": { + "name": "Other" + }, + "name": "Firefox Alpha", + "original": "Mozilla/5.0 (Windows NT 6.1; rv:15.0) Gecko/20120716 Firefox/15.0a2", + "os": { + "full": "Windows 7", + "name": "Windows", + "version": "7" + }, + "version": "15.0.a2" + } + }, + { + "@timestamp": "2016-12-07T10:05:07.000Z", + "_tmp": {}, + "ecs": { + "version": "8.5.1" + }, + "event": { + "category": [ + "web" + ], + "created": "2020-04-28T11:07:58.223Z", + "ingested": "2022-12-09T10:33:39.725718054Z", + "kind": "event", + "original": "10.0.0.2, 10.0.0.1, 67.43.156.14 - - [07/Dec/2016:11:05:07 +0100] \"GET /ocelot HTTP/1.1\" 200 571 \"-\" \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:49.0) Gecko/20100101 Firefox/49.0\"", + "outcome": "success", + "type": [ + "access" + ] + }, + "http": { + "request": { + "method": "GET" + }, + "response": { + "body": { + "bytes": 571 + }, + "status_code": 200 + }, + "version": "1.1" + }, + "nginx": { + "access": { + "remote_ip_list": [ + "10.0.0.2", + "10.0.0.1", + "67.43.156.14" + ] + } + }, + "related": { + "ip": [ + "67.43.156.14" + ] + }, + "source": { + "address": "67.43.156.14", + "as": { + "number": 35908 + }, + "geo": { + "continent_name": "Asia", + "country_iso_code": "BT", + "country_name": "Bhutan", + "location": { + "lat": 27.5, + "lon": 90.5 + } + }, + "ip": "67.43.156.14" + }, + "tags": [ + "preserve_original_event" + ], + "url": { + "original": "/ocelot", + "path": "/ocelot" + }, + "user_agent": { + "device": { + "name": "Mac" + }, + "name": "Firefox", + "original": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:49.0) Gecko/20100101 Firefox/49.0", + "os": { + "full": "Mac OS X 10.12", + "name": "Mac OS X", + "version": "10.12" + }, + "version": "49.0." + } + }, + { + "@timestamp": "2016-12-07T10:05:07.000Z", + "_tmp": {}, + "ecs": { + "version": "8.5.1" + }, + "event": { + "category": [ + "web" + ], + "created": "2020-04-28T11:07:58.223Z", + "ingested": "2022-12-09T10:33:39.725719804Z", + "kind": "event", + "original": "67.43.156.14 - - [07/Dec/2016:11:05:07 +0100] \"GET /ocelot HTTP/1.1\" 200 571 \"-\" \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36\"\n\"10.5.102.222, 199.96.1.1, 204.246.1.1\" 10.2.1.185 - - [22/Jan/2016:13:18:29 +0000] \"GET /assets/xxxx?q=100 HTTP/1.1\" 200 25507 \"-\" \"Amazon CloudFront\"\n2a02:cf40:add:4002:91f2:a9b2:e09a:6fc6, 10.225.192.17 10.2.2.121 - - [30/Dec/2016:06:47:09 +0000] \"GET /test.html HTTP/1.1\" 404 8571 \"-\" \"Mozilla/5.0 (compatible; Facebot 1.0; https://developers.facebook.com/docs/sharing/webmasters/crawler)\"", + "outcome": "success", + "type": [ + "access" + ] + }, + "http": { + "request": { + "method": "GET" + }, + "response": { + "body": { + "bytes": 571 + }, + "status_code": 200 + }, + "version": "1.1" + }, + "nginx": { + "access": { + "remote_ip_list": [ + "67.43.156.14" + ] + } + }, + "related": { + "ip": [ + "67.43.156.14" + ] + }, + "source": { + "address": "67.43.156.14", + "as": { + "number": 35908 + }, + "geo": { + "continent_name": "Asia", + "country_iso_code": "BT", + "country_name": "Bhutan", + "location": { + "lat": 27.5, + "lon": 90.5 + } + }, + "ip": "67.43.156.14" + }, + "tags": [ + "preserve_original_event" + ], + "url": { + "original": "/ocelot", + "path": "/ocelot" + }, + "user_agent": { + "device": { + "name": "Mac" + }, + "name": "Chrome", + "original": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36", + "os": { + "full": "Mac OS X 10.14.0", + "name": "Mac OS X", + "version": "10.14.0" + }, + "version": "70.0.3538.102" + } + }, + { + "@timestamp": "2018-04-12T07:48:40.000Z", + "ecs": { + "version": "8.5.1" + }, + "event": { + "category": [ + "web" + ], + "created": "2020-04-28T11:07:58.223Z", + "ingested": "2022-12-09T10:33:39.725721554Z", + "kind": "event", + "original": "127.0.0.1 - - [12/Apr/2018:09:48:40 +0200] \"\" 400 0 \"-\" \"-\"\nunix: - - [26/Feb/2019:15:39:42 +0100] \"hello\" 400 173 \"-\" \"-\"\nlocalhost - - [29/May/2017:19:02:48 +0000] \"GET /test2 HTTP/1.1\" 200 612 \"-\" \"Mozilla/5.0 (Windows NT 6.1; rv:15.0) Gecko/20120716 Firefox/15.0a2\" \"-\"\nlocalhost, localhost - - [29/May/2017:19:02:48 +0000] \"GET /test2 HTTP/1.1\" 200 612 \"-\" \"Mozilla/5.0 (Windows NT 6.1; rv:15.0) Gecko/20120716 Firefox/15.0a2\" \"-\"\n", + "outcome": "failure", + "type": [ + "access" + ] + }, + "http": { + "response": { + "body": { + "bytes": 0 + }, + "status_code": 400 + } + }, + "nginx": { + "access": { + "remote_ip_list": [ + "127.0.0.1" + ] + } + }, + "related": { + "ip": [ + "127.0.0.1" + ] + }, + "source": { + "address": "127.0.0.1", + "ip": "127.0.0.1" + }, + "tags": [ + "preserve_original_event" + ] + } + ] +} \ No newline at end of file diff --git a/integrations/nginx/samples/transformed-error_log.json b/integrations/nginx/samples/transformed-error_log.json new file mode 100644 index 000000000..4b3fab90d --- /dev/null +++ b/integrations/nginx/samples/transformed-error_log.json @@ -0,0 +1,148 @@ +{ + "result": [ + { + "@timestamp": "2016-10-25T14:49:34.000Z", + "ecs": { + "version": "8.5.1" + }, + "event": { + "category": [ + "web" + ], + "created": "2020-04-28T11:07:58.223Z", + "ingested": "2022-12-09T10:33:39.961425637Z", + "kind": "event", + "original": "2016/10/25 14:49:34 [error] 54053#0: *1 open() \"/usr/local/Cellar/nginx/1.10.2_1/html/favicon.ico\" failed (2: No such file or directory), client: 127.0.0.1, server: localhost, request: \"GET /favicon.ico HTTP/1.1\", host: \"localhost:8080\", referrer: \"http://localhost:8080/\"", + "type": [ + "error" + ] + }, + "log": { + "level": "error" + }, + "message": "open() \"/usr/local/Cellar/nginx/1.10.2_1/html/favicon.ico\" failed (2: No such file or directory), client: 127.0.0.1, server: localhost, request: \"GET /favicon.ico HTTP/1.1\", host: \"localhost:8080\", referrer: \"http://localhost:8080/\"", + "nginx": { + "error": { + "connection_id": 1 + } + }, + "process": { + "pid": 54053, + "thread": { + "id": 0 + } + }, + "tags": [ + "preserve_original_event" + ] + }, + { + "@timestamp": "2016-10-25T14:50:44.000Z", + "ecs": { + "version": "8.5.1" + }, + "event": { + "category": [ + "web" + ], + "created": "2020-04-28T11:07:58.223Z", + "ingested": "2022-12-09T10:33:39.961441971Z", + "kind": "event", + "original": "2016/10/25 14:50:44 [error] 54053#0: *3 open() \"/usr/local/Cellar/nginx/1.10.2_1/html/adsasd\" failed (2: No such file or directory), client: 127.0.0.1, server: localhost, request: \"GET /adsasd HTTP/1.1\", host: \"localhost:8080\"", + "type": [ + "error" + ] + }, + "log": { + "level": "error" + }, + "message": "open() \"/usr/local/Cellar/nginx/1.10.2_1/html/adsasd\" failed (2: No such file or directory), client: 127.0.0.1, server: localhost, request: \"GET /adsasd HTTP/1.1\", host: \"localhost:8080\"", + "nginx": { + "error": { + "connection_id": 3 + } + }, + "process": { + "pid": 54053, + "thread": { + "id": 0 + } + }, + "tags": [ + "preserve_original_event" + ] + }, + { + "@timestamp": "2019-10-30T23:26:34.000Z", + "ecs": { + "version": "8.5.1" + }, + "event": { + "category": [ + "web" + ], + "created": "2020-04-28T11:07:58.223Z", + "ingested": "2022-12-09T10:33:39.961444512Z", + "kind": "event", + "original": "2019/10/30 23:26:34 [error] 205860#205860: *180289 FastCGI sent in stderr: \"PHP message: PHP Warning: Declaration of FEE_Field_Terms::wrap($content, $taxonomy, $before, $sep, $after) should be compatible with FEE_Field_Post::wrap($content, $post_id = 0) in /var/www/xxx/web/wp-content/plugins/front-end-editor/php/fields/post.php on line 0\nPHP message: PHP Warning: Declaration of FEE_Field_Tags::wrap($content, $before, $sep, $after) should be compatible with FEE_Field_Terms::wrap($content, $taxonomy, $before, $sep, $after) in /var/www/xxx/web/wp-content/plugins/front-end-editor/php/fields/post.php on line 0\nPHP message: PHP Warning: Declaration of FEE_Field_Category::wrap($content, $sep, $parents) should be compatible with FEE_Field_Terms::wrap($content, $taxonomy, $before, $sep, $after) in /var/www/xxx/web/wp-content/plugins/front-end-editor/php/fields/post.php on line 0", + "type": [ + "error" + ] + }, + "log": { + "level": "error" + }, + "message": "FastCGI sent in stderr: \"PHP message: PHP Warning: Declaration of FEE_Field_Terms::wrap($content, $taxonomy, $before, $sep, $after) should be compatible with FEE_Field_Post::wrap($content, $post_id = 0) in /var/www/xxx/web/wp-content/plugins/front-end-editor/php/fields/post.php on line 0\nPHP message: PHP Warning: Declaration of FEE_Field_Tags::wrap($content, $before, $sep, $after) should be compatible with FEE_Field_Terms::wrap($content, $taxonomy, $before, $sep, $after) in /var/www/xxx/web/wp-content/plugins/front-end-editor/php/fields/post.php on line 0\nPHP message: PHP Warning: Declaration of FEE_Field_Category::wrap($content, $sep, $parents) should be compatible with FEE_Field_Terms::wrap($content, $taxonomy, $before, $sep, $after) in /var/www/xxx/web/wp-content/plugins/front-end-editor/php/fields/post.php on line 0", + "nginx": { + "error": { + "connection_id": 180289 + } + }, + "process": { + "pid": 205860, + "thread": { + "id": 205860 + } + }, + "tags": [ + "preserve_original_event" + ] + }, + { + "@timestamp": "2019-11-05T14:50:44.000Z", + "ecs": { + "version": "8.5.1" + }, + "event": { + "category": [ + "web" + ], + "created": "2020-04-28T11:07:58.223Z", + "ingested": "2022-12-09T10:33:39.961446596Z", + "kind": "event", + "original": "2019/11/05 14:50:44 [error] 54053#0: *3 open() \"/usr/local/Cellar/nginx/1.10.2_1/html/adsasd\" failed (2: No such file or directory), client: 127.0.0.1, server: localhost, request: \"GET /pysio HTTP/1.1\", host: \"localhost:8080\"", + "type": [ + "error" + ] + }, + "log": { + "level": "error" + }, + "message": "open() \"/usr/local/Cellar/nginx/1.10.2_1/html/adsasd\" failed (2: No such file or directory), client: 127.0.0.1, server: localhost, request: \"GET /pysio HTTP/1.1\", host: \"localhost:8080\"", + "nginx": { + "error": { + "connection_id": 3 + } + }, + "process": { + "pid": 54053, + "thread": { + "id": 0 + } + }, + "tags": [ + "preserve_original_event" + ] + } + ] +} \ No newline at end of file diff --git a/integrations/nginx/samples/transformed-metrics_log.json b/integrations/nginx/samples/transformed-metrics_log.json new file mode 100644 index 000000000..5362c699e --- /dev/null +++ b/integrations/nginx/samples/transformed-metrics_log.json @@ -0,0 +1,3 @@ +{ + "result": [] +} \ No newline at end of file diff --git a/integrations/nginx/schema/README.md b/integrations/nginx/schema/README.md new file mode 100644 index 000000000..0b06c9d07 --- /dev/null +++ b/integrations/nginx/schema/README.md @@ -0,0 +1,35 @@ +# Schema +The schema folder is where the actual translation is done between the Nginx format (logs/metrics) and the `sso` [Observability format](../../../schema/observability/README.md) + +## Nginx Log Format +Nginx log format refers to the way Nginx web server records information about incoming HTTP requests and outgoing responses in its access log files. The log format is configurable, meaning that you can choose what information is logged, and in what format. + +Here is an example of a typical Nginx log format: +```text +log_format combined '$remote_addr - $remote_user [$time_local] ' + '"$request" $status $body_bytes_sent ' + '"$http_referer" "$http_user_agent"'; + +``` + + - `$remote_addr`: The IP address of the client making the request. + - `$remote_user`: The username provided by the client, if any. + - `$time_local`: The date and time of the request in the local timezone. + - `$request`: The HTTP request method, URI, and protocol used by the client. + - `$status`: The HTTP status code returned by the server. + - `$body_bytes_sent`: The number of bytes sent in the response body. + - `$http_referer`: The URL of the page that referred the client to the current page. + - `$http_user_agent`: The user agent string provided by the client, typically identifying the client's web browser or other software. + +By default, Nginx logs are stored in the `/var/log/nginx/access.log` file on Linux systems, but this can be customized in the server block of the Nginx configuration file. + +Custom log formats can be defined by modifying the `log_format` directive in the Nginx configuration file. For example, you can remove or add fields to the log format, or change the order in which they appear in the log file. + +### Schema Folder + +Each sub-folder represents a different observability signals provider that can be used to translate and deliver `sso` compatible events from nginx to opensearch. + + +### Fluent-bit +This data collector has a dedicated agent for nginx which can use a [dedicated lua parser](fluent-bit/parsers.conf) that converts nginx original log format into sso logs format. + diff --git a/integrations/nginx/schema/fluent-bit/parsers.conf b/integrations/nginx/schema/fluent-bit/parsers.conf new file mode 100644 index 000000000..d68f38b1a --- /dev/null +++ b/integrations/nginx/schema/fluent-bit/parsers.conf @@ -0,0 +1,126 @@ +[PARSER] +Name apache +Format regex +Regex ^(?[^ ]*) [^ ]* (?[^ ]*) \[(?

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 diff --git a/integrations/nginx/samples/result/nginx_access-log.json b/integrations/nginx/samples/result/nginx_access-log.json deleted file mode 100644 index 8a316430b..000000000 --- a/integrations/nginx/samples/result/nginx_access-log.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "@timestamp": "2022-12-09T10:39:23.000Z", - "observerTime": "2022-12-09T10:39:38.896Z", - "body": "47.29.201.179 - - [01/Mar/2020:10:34:43 +0100] \"GET / HTTP/1.1\" 200 612 \"-\" \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.119 Safari/537.36\"", - "trace_id":"102981ABCD2901", - "span_id":"abcdef1010", - "attributes": { - "data_stream": { - "dataset": "nginx.access", - "namespace": "production", - "type": "logs" - } - }, - "event": { - "category": [ - "web" - ], - "name": "access", - "domain": "nginx.access", - "kind": "event", - "result": "success", - "type": [ - "access" - ] - }, - "http": { - "request": { - "method": "GET" - }, - "response": { - "bytes": 97, - "status_code": "200" - }, - "flavor": "1.1", - "url": "/server-status" - }, - "communication": { - "source": { - "address": "127.0.0.1", - "ip": "127.0.0.1" - } - } -} \ No newline at end of file diff --git a/integrations/nginx/samples/transformed-access_log.json b/integrations/nginx/samples/transformed-access_log.json deleted file mode 100644 index 0e4a4ee6a..000000000 --- a/integrations/nginx/samples/transformed-access_log.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "result": [ - { - "@timestamp": "2016-12-07T10:05:07.000Z", - "_tmp": {}, - "ecs": { - "version": "8.5.1" - }, - "event": { - "category": [ - "web" - ], - "created": "2020-04-28T11:07:58.223Z", - "ingested": "2022-12-09T10:33:39.725697721Z", - "kind": "event", - "original": "10.0.0.2, 10.0.0.1, 127.0.0.1 - - [07/Dec/2016:11:05:07 +0100] \"GET /ocelot HTTP/1.1\" 200 571 \"-\" \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:49.0) Gecko/20100101 Firefox/49.0\"", - "outcome": "success", - "type": [ - "access" - ] - }, - "http": { - "request": { - "method": "GET" - }, - "response": { - "body": { - "bytes": 571 - }, - "status_code": 200 - }, - "version": "1.1" - }, - "nginx": { - "access": { - "remote_ip_list": [ - "10.0.0.2", - "10.0.0.1", - "127.0.0.1" - ] - } - }, - "related": { - "ip": [ - "10.0.0.2" - ] - }, - "source": { - "address": "10.0.0.2", - "ip": "10.0.0.2" - }, - "tags": [ - "preserve_original_event" - ], - "url": { - "original": "/ocelot", - "path": "/ocelot" - }, - "user_agent": { - "device": { - "name": "Mac" - }, - "name": "Firefox", - "original": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:49.0) Gecko/20100101 Firefox/49.0", - "os": { - "full": "Mac OS X 10.12", - "name": "Mac OS X", - "version": "10.12" - }, - "version": "49.0." - } - }, - { - "@timestamp": "2017-05-29T19:02:48.000Z", - "_tmp": {}, - "ecs": { - "version": "8.5.1" - }, - "event": { - "category": [ - "web" - ], - "created": "2020-04-28T11:07:58.223Z", - "ingested": "2022-12-09T10:33:39.725715762Z", - "kind": "event", - "original": "172.17.0.1 - - [29/May/2017:19:02:48 +0000] \"GET /stringpatch HTTP/1.1\" 404 612 \"-\" \"Mozilla/5.0 (Windows NT 6.1; rv:15.0) Gecko/20120716 Firefox/15.0a2\" \"-\"", - "outcome": "failure", - "type": [ - "access" - ] - }, - "http": { - "request": { - "method": "GET" - }, - "response": { - "body": { - "bytes": 612 - }, - "status_code": 404 - }, - "version": "1.1" - }, - "nginx": { - "access": { - "remote_ip_list": [ - "172.17.0.1" - ] - } - }, - "related": { - "ip": [ - "172.17.0.1" - ] - }, - "source": { - "address": "172.17.0.1", - "ip": "172.17.0.1" - }, - "tags": [ - "preserve_original_event" - ], - "url": { - "original": "/stringpatch", - "path": "/stringpatch" - }, - "user_agent": { - "device": { - "name": "Other" - }, - "name": "Firefox Alpha", - "original": "Mozilla/5.0 (Windows NT 6.1; rv:15.0) Gecko/20120716 Firefox/15.0a2", - "os": { - "full": "Windows 7", - "name": "Windows", - "version": "7" - }, - "version": "15.0.a2" - } - }, - { - "@timestamp": "2016-12-07T10:05:07.000Z", - "_tmp": {}, - "ecs": { - "version": "8.5.1" - }, - "event": { - "category": [ - "web" - ], - "created": "2020-04-28T11:07:58.223Z", - "ingested": "2022-12-09T10:33:39.725718054Z", - "kind": "event", - "original": "10.0.0.2, 10.0.0.1, 67.43.156.14 - - [07/Dec/2016:11:05:07 +0100] \"GET /ocelot HTTP/1.1\" 200 571 \"-\" \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:49.0) Gecko/20100101 Firefox/49.0\"", - "outcome": "success", - "type": [ - "access" - ] - }, - "http": { - "request": { - "method": "GET" - }, - "response": { - "body": { - "bytes": 571 - }, - "status_code": 200 - }, - "version": "1.1" - }, - "nginx": { - "access": { - "remote_ip_list": [ - "10.0.0.2", - "10.0.0.1", - "67.43.156.14" - ] - } - }, - "related": { - "ip": [ - "67.43.156.14" - ] - }, - "source": { - "address": "67.43.156.14", - "as": { - "number": 35908 - }, - "geo": { - "continent_name": "Asia", - "country_iso_code": "BT", - "country_name": "Bhutan", - "location": { - "lat": 27.5, - "lon": 90.5 - } - }, - "ip": "67.43.156.14" - }, - "tags": [ - "preserve_original_event" - ], - "url": { - "original": "/ocelot", - "path": "/ocelot" - }, - "user_agent": { - "device": { - "name": "Mac" - }, - "name": "Firefox", - "original": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:49.0) Gecko/20100101 Firefox/49.0", - "os": { - "full": "Mac OS X 10.12", - "name": "Mac OS X", - "version": "10.12" - }, - "version": "49.0." - } - }, - { - "@timestamp": "2016-12-07T10:05:07.000Z", - "_tmp": {}, - "ecs": { - "version": "8.5.1" - }, - "event": { - "category": [ - "web" - ], - "created": "2020-04-28T11:07:58.223Z", - "ingested": "2022-12-09T10:33:39.725719804Z", - "kind": "event", - "original": "67.43.156.14 - - [07/Dec/2016:11:05:07 +0100] \"GET /ocelot HTTP/1.1\" 200 571 \"-\" \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36\"\n\"10.5.102.222, 199.96.1.1, 204.246.1.1\" 10.2.1.185 - - [22/Jan/2016:13:18:29 +0000] \"GET /assets/xxxx?q=100 HTTP/1.1\" 200 25507 \"-\" \"Amazon CloudFront\"\n2a02:cf40:add:4002:91f2:a9b2:e09a:6fc6, 10.225.192.17 10.2.2.121 - - [30/Dec/2016:06:47:09 +0000] \"GET /test.html HTTP/1.1\" 404 8571 \"-\" \"Mozilla/5.0 (compatible; Facebot 1.0; https://developers.facebook.com/docs/sharing/webmasters/crawler)\"", - "outcome": "success", - "type": [ - "access" - ] - }, - "http": { - "request": { - "method": "GET" - }, - "response": { - "body": { - "bytes": 571 - }, - "status_code": 200 - }, - "version": "1.1" - }, - "nginx": { - "access": { - "remote_ip_list": [ - "67.43.156.14" - ] - } - }, - "related": { - "ip": [ - "67.43.156.14" - ] - }, - "source": { - "address": "67.43.156.14", - "as": { - "number": 35908 - }, - "geo": { - "continent_name": "Asia", - "country_iso_code": "BT", - "country_name": "Bhutan", - "location": { - "lat": 27.5, - "lon": 90.5 - } - }, - "ip": "67.43.156.14" - }, - "tags": [ - "preserve_original_event" - ], - "url": { - "original": "/ocelot", - "path": "/ocelot" - }, - "user_agent": { - "device": { - "name": "Mac" - }, - "name": "Chrome", - "original": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36", - "os": { - "full": "Mac OS X 10.14.0", - "name": "Mac OS X", - "version": "10.14.0" - }, - "version": "70.0.3538.102" - } - }, - { - "@timestamp": "2018-04-12T07:48:40.000Z", - "ecs": { - "version": "8.5.1" - }, - "event": { - "category": [ - "web" - ], - "created": "2020-04-28T11:07:58.223Z", - "ingested": "2022-12-09T10:33:39.725721554Z", - "kind": "event", - "original": "127.0.0.1 - - [12/Apr/2018:09:48:40 +0200] \"\" 400 0 \"-\" \"-\"\nunix: - - [26/Feb/2019:15:39:42 +0100] \"hello\" 400 173 \"-\" \"-\"\nlocalhost - - [29/May/2017:19:02:48 +0000] \"GET /test2 HTTP/1.1\" 200 612 \"-\" \"Mozilla/5.0 (Windows NT 6.1; rv:15.0) Gecko/20120716 Firefox/15.0a2\" \"-\"\nlocalhost, localhost - - [29/May/2017:19:02:48 +0000] \"GET /test2 HTTP/1.1\" 200 612 \"-\" \"Mozilla/5.0 (Windows NT 6.1; rv:15.0) Gecko/20120716 Firefox/15.0a2\" \"-\"\n", - "outcome": "failure", - "type": [ - "access" - ] - }, - "http": { - "response": { - "body": { - "bytes": 0 - }, - "status_code": 400 - } - }, - "nginx": { - "access": { - "remote_ip_list": [ - "127.0.0.1" - ] - } - }, - "related": { - "ip": [ - "127.0.0.1" - ] - }, - "source": { - "address": "127.0.0.1", - "ip": "127.0.0.1" - }, - "tags": [ - "preserve_original_event" - ] - } - ] -} \ No newline at end of file diff --git a/integrations/nginx/samples/transformed-error_log.json b/integrations/nginx/samples/transformed-error_log.json deleted file mode 100644 index 4b3fab90d..000000000 --- a/integrations/nginx/samples/transformed-error_log.json +++ /dev/null @@ -1,148 +0,0 @@ -{ - "result": [ - { - "@timestamp": "2016-10-25T14:49:34.000Z", - "ecs": { - "version": "8.5.1" - }, - "event": { - "category": [ - "web" - ], - "created": "2020-04-28T11:07:58.223Z", - "ingested": "2022-12-09T10:33:39.961425637Z", - "kind": "event", - "original": "2016/10/25 14:49:34 [error] 54053#0: *1 open() \"/usr/local/Cellar/nginx/1.10.2_1/html/favicon.ico\" failed (2: No such file or directory), client: 127.0.0.1, server: localhost, request: \"GET /favicon.ico HTTP/1.1\", host: \"localhost:8080\", referrer: \"http://localhost:8080/\"", - "type": [ - "error" - ] - }, - "log": { - "level": "error" - }, - "message": "open() \"/usr/local/Cellar/nginx/1.10.2_1/html/favicon.ico\" failed (2: No such file or directory), client: 127.0.0.1, server: localhost, request: \"GET /favicon.ico HTTP/1.1\", host: \"localhost:8080\", referrer: \"http://localhost:8080/\"", - "nginx": { - "error": { - "connection_id": 1 - } - }, - "process": { - "pid": 54053, - "thread": { - "id": 0 - } - }, - "tags": [ - "preserve_original_event" - ] - }, - { - "@timestamp": "2016-10-25T14:50:44.000Z", - "ecs": { - "version": "8.5.1" - }, - "event": { - "category": [ - "web" - ], - "created": "2020-04-28T11:07:58.223Z", - "ingested": "2022-12-09T10:33:39.961441971Z", - "kind": "event", - "original": "2016/10/25 14:50:44 [error] 54053#0: *3 open() \"/usr/local/Cellar/nginx/1.10.2_1/html/adsasd\" failed (2: No such file or directory), client: 127.0.0.1, server: localhost, request: \"GET /adsasd HTTP/1.1\", host: \"localhost:8080\"", - "type": [ - "error" - ] - }, - "log": { - "level": "error" - }, - "message": "open() \"/usr/local/Cellar/nginx/1.10.2_1/html/adsasd\" failed (2: No such file or directory), client: 127.0.0.1, server: localhost, request: \"GET /adsasd HTTP/1.1\", host: \"localhost:8080\"", - "nginx": { - "error": { - "connection_id": 3 - } - }, - "process": { - "pid": 54053, - "thread": { - "id": 0 - } - }, - "tags": [ - "preserve_original_event" - ] - }, - { - "@timestamp": "2019-10-30T23:26:34.000Z", - "ecs": { - "version": "8.5.1" - }, - "event": { - "category": [ - "web" - ], - "created": "2020-04-28T11:07:58.223Z", - "ingested": "2022-12-09T10:33:39.961444512Z", - "kind": "event", - "original": "2019/10/30 23:26:34 [error] 205860#205860: *180289 FastCGI sent in stderr: \"PHP message: PHP Warning: Declaration of FEE_Field_Terms::wrap($content, $taxonomy, $before, $sep, $after) should be compatible with FEE_Field_Post::wrap($content, $post_id = 0) in /var/www/xxx/web/wp-content/plugins/front-end-editor/php/fields/post.php on line 0\nPHP message: PHP Warning: Declaration of FEE_Field_Tags::wrap($content, $before, $sep, $after) should be compatible with FEE_Field_Terms::wrap($content, $taxonomy, $before, $sep, $after) in /var/www/xxx/web/wp-content/plugins/front-end-editor/php/fields/post.php on line 0\nPHP message: PHP Warning: Declaration of FEE_Field_Category::wrap($content, $sep, $parents) should be compatible with FEE_Field_Terms::wrap($content, $taxonomy, $before, $sep, $after) in /var/www/xxx/web/wp-content/plugins/front-end-editor/php/fields/post.php on line 0", - "type": [ - "error" - ] - }, - "log": { - "level": "error" - }, - "message": "FastCGI sent in stderr: \"PHP message: PHP Warning: Declaration of FEE_Field_Terms::wrap($content, $taxonomy, $before, $sep, $after) should be compatible with FEE_Field_Post::wrap($content, $post_id = 0) in /var/www/xxx/web/wp-content/plugins/front-end-editor/php/fields/post.php on line 0\nPHP message: PHP Warning: Declaration of FEE_Field_Tags::wrap($content, $before, $sep, $after) should be compatible with FEE_Field_Terms::wrap($content, $taxonomy, $before, $sep, $after) in /var/www/xxx/web/wp-content/plugins/front-end-editor/php/fields/post.php on line 0\nPHP message: PHP Warning: Declaration of FEE_Field_Category::wrap($content, $sep, $parents) should be compatible with FEE_Field_Terms::wrap($content, $taxonomy, $before, $sep, $after) in /var/www/xxx/web/wp-content/plugins/front-end-editor/php/fields/post.php on line 0", - "nginx": { - "error": { - "connection_id": 180289 - } - }, - "process": { - "pid": 205860, - "thread": { - "id": 205860 - } - }, - "tags": [ - "preserve_original_event" - ] - }, - { - "@timestamp": "2019-11-05T14:50:44.000Z", - "ecs": { - "version": "8.5.1" - }, - "event": { - "category": [ - "web" - ], - "created": "2020-04-28T11:07:58.223Z", - "ingested": "2022-12-09T10:33:39.961446596Z", - "kind": "event", - "original": "2019/11/05 14:50:44 [error] 54053#0: *3 open() \"/usr/local/Cellar/nginx/1.10.2_1/html/adsasd\" failed (2: No such file or directory), client: 127.0.0.1, server: localhost, request: \"GET /pysio HTTP/1.1\", host: \"localhost:8080\"", - "type": [ - "error" - ] - }, - "log": { - "level": "error" - }, - "message": "open() \"/usr/local/Cellar/nginx/1.10.2_1/html/adsasd\" failed (2: No such file or directory), client: 127.0.0.1, server: localhost, request: \"GET /pysio HTTP/1.1\", host: \"localhost:8080\"", - "nginx": { - "error": { - "connection_id": 3 - } - }, - "process": { - "pid": 54053, - "thread": { - "id": 0 - } - }, - "tags": [ - "preserve_original_event" - ] - } - ] -} \ No newline at end of file diff --git a/integrations/nginx/samples/transformed-metrics_log.json b/integrations/nginx/samples/transformed-metrics_log.json deleted file mode 100644 index 5362c699e..000000000 --- a/integrations/nginx/samples/transformed-metrics_log.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "result": [] -} \ No newline at end of file diff --git a/integrations/nginx/schema/README.md b/integrations/nginx/schema/README.md deleted file mode 100644 index 0b06c9d07..000000000 --- a/integrations/nginx/schema/README.md +++ /dev/null @@ -1,35 +0,0 @@ -# Schema -The schema folder is where the actual translation is done between the Nginx format (logs/metrics) and the `sso` [Observability format](../../../schema/observability/README.md) - -## Nginx Log Format -Nginx log format refers to the way Nginx web server records information about incoming HTTP requests and outgoing responses in its access log files. The log format is configurable, meaning that you can choose what information is logged, and in what format. - -Here is an example of a typical Nginx log format: -```text -log_format combined '$remote_addr - $remote_user [$time_local] ' - '"$request" $status $body_bytes_sent ' - '"$http_referer" "$http_user_agent"'; - -``` - - - `$remote_addr`: The IP address of the client making the request. - - `$remote_user`: The username provided by the client, if any. - - `$time_local`: The date and time of the request in the local timezone. - - `$request`: The HTTP request method, URI, and protocol used by the client. - - `$status`: The HTTP status code returned by the server. - - `$body_bytes_sent`: The number of bytes sent in the response body. - - `$http_referer`: The URL of the page that referred the client to the current page. - - `$http_user_agent`: The user agent string provided by the client, typically identifying the client's web browser or other software. - -By default, Nginx logs are stored in the `/var/log/nginx/access.log` file on Linux systems, but this can be customized in the server block of the Nginx configuration file. - -Custom log formats can be defined by modifying the `log_format` directive in the Nginx configuration file. For example, you can remove or add fields to the log format, or change the order in which they appear in the log file. - -### Schema Folder - -Each sub-folder represents a different observability signals provider that can be used to translate and deliver `sso` compatible events from nginx to opensearch. - - -### Fluent-bit -This data collector has a dedicated agent for nginx which can use a [dedicated lua parser](fluent-bit/parsers.conf) that converts nginx original log format into sso logs format. - diff --git a/integrations/nginx/schema/fluent-bit/parsers.conf b/integrations/nginx/schema/fluent-bit/parsers.conf deleted file mode 100644 index d68f38b1a..000000000 --- a/integrations/nginx/schema/fluent-bit/parsers.conf +++ /dev/null @@ -1,126 +0,0 @@ -[PARSER] -Name apache -Format regex -Regex ^(?[^ ]*) [^ ]* (?[^ ]*) \[(?