This commit is contained in:
Amaury Chamayou 2021-09-27 13:20:32 +01:00 коммит произвёл GitHub
Родитель 674b5c1e80
Коммит 41cadaf415
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
16 изменённых файлов: 140 добавлений и 91 удалений

Просмотреть файл

@ -8,7 +8,8 @@ trigger:
jobs:
- job: build_and_publish_docs
container: ccfciteam/ccf-ci:oe0.17.2-docker-cli
pool: 1es-dv4-focal
pool:
vmImage: ubuntu-20.04
steps:
- checkout: self

Просмотреть файл

@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
### Added
- Receipts now include the endorsed certificate of the node, as well as its node id, for convenience.
- `get_metrics_v1` API to `BaseEndpointRegistry` for applications that do not make use of builtins and want to version or customise metrics output.
## [2.0.0-dev4]

Просмотреть файл

@ -29,6 +29,14 @@ Application Endpoint Registration
:project: CCF
:members:
.. doxygenstruct:: ccf::EndpointMetricsEntry
:project: CCF
:members:
.. doxygenstruct:: ccf::EndpointMetrics
:project: CCF
:members:
.. doxygenclass:: ccf::BaseEndpointRegistry
:project: CCF
:members:

Просмотреть файл

@ -7,7 +7,18 @@
],
"type": "string"
},
"EndpointMetrics__Entry": {
"EndpointMetrics": {
"properties": {
"metrics": {
"$ref": "#/components/schemas/EndpointMetricsEntry_array"
}
},
"required": [
"metrics"
],
"type": "object"
},
"EndpointMetricsEntry": {
"properties": {
"calls": {
"$ref": "#/components/schemas/uint64"
@ -38,23 +49,12 @@
],
"type": "object"
},
"EndpointMetrics__Entry_array": {
"EndpointMetricsEntry_array": {
"items": {
"$ref": "#/components/schemas/EndpointMetrics__Entry"
"$ref": "#/components/schemas/EndpointMetricsEntry"
},
"type": "array"
},
"EndpointMetrics__Out": {
"properties": {
"metrics": {
"$ref": "#/components/schemas/EndpointMetrics__Entry_array"
}
},
"required": [
"metrics"
],
"type": "object"
},
"EntityId": {
"format": "hex",
"pattern": "^[a-f0-9]{64}$",
@ -338,7 +338,7 @@
"info": {
"description": "This CCF sample app implements a simple logging application, securely recording messages at client-specified IDs. It demonstrates most of the features available to CCF apps.",
"title": "CCF Sample Logging App",
"version": "1.1.0"
"version": "1.2.0"
},
"openapi": "3.0.0",
"paths": {
@ -365,7 +365,7 @@
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/EndpointMetrics__Out"
"$ref": "#/components/schemas/EndpointMetrics"
}
}
},

Просмотреть файл

@ -39,7 +39,18 @@
],
"type": "string"
},
"EndpointMetrics__Entry": {
"EndpointMetrics": {
"properties": {
"metrics": {
"$ref": "#/components/schemas/EndpointMetricsEntry_array"
}
},
"required": [
"metrics"
],
"type": "object"
},
"EndpointMetricsEntry": {
"properties": {
"calls": {
"$ref": "#/components/schemas/uint64"
@ -70,23 +81,12 @@
],
"type": "object"
},
"EndpointMetrics__Entry_array": {
"EndpointMetricsEntry_array": {
"items": {
"$ref": "#/components/schemas/EndpointMetrics__Entry"
"$ref": "#/components/schemas/EndpointMetricsEntry"
},
"type": "array"
},
"EndpointMetrics__Out": {
"properties": {
"metrics": {
"$ref": "#/components/schemas/EndpointMetrics__Entry_array"
}
},
"required": [
"metrics"
],
"type": "object"
},
"EntityId": {
"format": "hex",
"pattern": "^[a-f0-9]{64}$",
@ -400,7 +400,7 @@
"info": {
"description": "This API is used to submit and query proposals which affect CCF's public governance tables.",
"title": "CCF Governance API",
"version": "2.1.0"
"version": "2.2.0"
},
"openapi": "3.0.0",
"paths": {
@ -472,7 +472,7 @@
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/EndpointMetrics__Out"
"$ref": "#/components/schemas/EndpointMetrics"
}
}
},

Просмотреть файл

@ -7,7 +7,18 @@
],
"type": "string"
},
"EndpointMetrics__Entry": {
"EndpointMetrics": {
"properties": {
"metrics": {
"$ref": "#/components/schemas/EndpointMetricsEntry_array"
}
},
"required": [
"metrics"
],
"type": "object"
},
"EndpointMetricsEntry": {
"properties": {
"calls": {
"$ref": "#/components/schemas/uint64"
@ -38,23 +49,12 @@
],
"type": "object"
},
"EndpointMetrics__Entry_array": {
"EndpointMetricsEntry_array": {
"items": {
"$ref": "#/components/schemas/EndpointMetrics__Entry"
"$ref": "#/components/schemas/EndpointMetricsEntry"
},
"type": "array"
},
"EndpointMetrics__Out": {
"properties": {
"metrics": {
"$ref": "#/components/schemas/EndpointMetrics__Entry_array"
}
},
"required": [
"metrics"
],
"type": "object"
},
"EntityId": {
"format": "hex",
"pattern": "^[a-f0-9]{64}$",
@ -494,7 +494,7 @@
"info": {
"description": "This API provides public, uncredentialed access to service and node state.",
"title": "CCF Public Node API",
"version": "2.1.0"
"version": "2.2.0"
},
"openapi": "3.0.0",
"paths": {
@ -521,7 +521,7 @@
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/EndpointMetrics__Out"
"$ref": "#/components/schemas/EndpointMetrics"
}
}
},

Просмотреть файл

@ -156,5 +156,10 @@ namespace ccf
/** Get untrusted time from the host of the currently executing node.
*/
ApiResult get_untrusted_host_time_v1(::timespec& time);
/** Get usage metrics from endpoints under the registry, including
* number of calls, errors, failures and retries.
*/
ApiResult get_metrics_v1(EndpointMetrics& endpoint_metrics);
};
}

Просмотреть файл

@ -10,6 +10,7 @@
#include "ds/openapi.h"
#include "http/http_consts.h"
#include "node/certs.h"
#include "node/endpoint_metrics.h"
#include "node/rpc/serialization.h"
#include <charconv>

Просмотреть файл

@ -1191,7 +1191,7 @@ namespace loggingapp
"This CCF sample app implements a simple logging application, securely "
"recording messages at client-specified IDs. It demonstrates most of "
"the features available to CCF apps.";
logger_handlers.openapi_info.document_version = "1.1.0";
logger_handlers.openapi_info.document_version = "1.2.0";
}
};
}

Просмотреть файл

@ -280,4 +280,25 @@ namespace ccf
return ApiResult::OK;
}
ApiResult BaseEndpointRegistry::get_metrics_v1(
EndpointMetrics& endpoint_metrics)
{
endpoint_metrics.metrics.clear();
std::lock_guard<std::mutex> guard(metrics_lock);
for (const auto& [path, verb_metrics] : metrics)
{
for (const auto& [verb, metric] : verb_metrics)
{
endpoint_metrics.metrics.push_back(
{path,
verb,
metric.calls,
metric.errors,
metric.failures,
metric.retries});
}
}
return ApiResult::OK;
}
}

Просмотреть файл

@ -197,29 +197,26 @@ namespace ccf
.install();
auto endpoint_metrics_fn = [this](auto&, nlohmann::json&&) {
std::lock_guard<std::mutex> guard(metrics_lock);
EndpointMetrics::Out out;
for (const auto& [path, verb_metrics] : metrics)
EndpointMetrics out;
const auto result = get_metrics_v1(out);
if (result == ccf::ApiResult::OK)
{
for (const auto& [verb, metric] : verb_metrics)
{
out.metrics.push_back(
{path,
verb,
metric.calls,
metric.errors,
metric.failures,
metric.retries});
}
return make_success(out);
}
else
{
return make_error(
HTTP_STATUS_INTERNAL_SERVER_ERROR,
ccf::errors::InternalError,
fmt::format("Error code: {}", ccf::api_result_to_str(result)));
}
return make_success(out);
};
make_command_endpoint(
"/api/metrics",
HTTP_GET,
json_command_adapter(endpoint_metrics_fn),
no_auth_required)
.set_auto_schema<void, EndpointMetrics::Out>()
.set_auto_schema<void, EndpointMetrics>()
.set_execute_outside_consensus(
ccf::endpoints::ExecuteOutsideConsensus::Locally)
.install();

Просмотреть файл

@ -0,0 +1,39 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the Apache 2.0 License.
#pragma once
#include "ds/json.h"
#include <vector>
namespace ccf
{
struct EndpointMetricsEntry
{
/// Endpoint path
std::string path;
/// Endpoint method
std::string method;
/// Number of calls since node start
size_t calls = 0;
/// Number of errors (4xx) since node start
size_t errors = 0;
/// Number of failures (5xx) since node start
size_t failures = 0;
/// Number of transaction retries caused by
/// conflicts since node start
size_t retries = 0;
};
struct EndpointMetrics
{
/// Metrics for all endpoints in the frontend
std::vector<EndpointMetricsEntry> metrics;
};
DECLARE_JSON_TYPE(EndpointMetricsEntry)
DECLARE_JSON_REQUIRED_FIELDS(
EndpointMetricsEntry, path, method, calls, errors, failures, retries)
DECLARE_JSON_TYPE(EndpointMetrics)
DECLARE_JSON_REQUIRED_FIELDS(EndpointMetrics, metrics)
}

Просмотреть файл

@ -91,24 +91,6 @@ namespace ccf
using Out = nlohmann::json;
};
struct EndpointMetrics
{
struct Entry
{
std::string path;
std::string method;
size_t calls = 0;
size_t errors = 0;
size_t failures = 0;
size_t retries = 0;
};
struct Out
{
std::vector<Entry> metrics;
};
};
struct VerifyReceipt
{
struct In

Просмотреть файл

@ -482,7 +482,7 @@ namespace ccf
openapi_info.description =
"This API is used to submit and query proposals which affect CCF's "
"public governance tables.";
openapi_info.document_version = "2.1.0";
openapi_info.document_version = "2.2.0";
}
static std::optional<MemberId> get_caller_member_id(

Просмотреть файл

@ -285,7 +285,7 @@ namespace ccf
openapi_info.description =
"This API provides public, uncredentialed access to service and node "
"state.";
openapi_info.document_version = "2.1.0";
openapi_info.document_version = "2.2.0";
}
void init_handlers() override

Просмотреть файл

@ -117,12 +117,6 @@ namespace ccf
DECLARE_JSON_TYPE(GetNodes::Out)
DECLARE_JSON_REQUIRED_FIELDS(GetNodes::Out, nodes)
DECLARE_JSON_TYPE(EndpointMetrics::Entry)
DECLARE_JSON_REQUIRED_FIELDS(
EndpointMetrics::Entry, path, method, calls, errors, failures, retries)
DECLARE_JSON_TYPE(EndpointMetrics::Out)
DECLARE_JSON_REQUIRED_FIELDS(EndpointMetrics::Out, metrics)
DECLARE_JSON_TYPE(VerifyReceipt::In)
DECLARE_JSON_REQUIRED_FIELDS(VerifyReceipt::In, receipt)
DECLARE_JSON_TYPE(VerifyReceipt::Out)