| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190 |
- /*
- * Copyright (c) 2022 Project CHIP Authors
- * All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
- #pragma once
- #include <string>
- #include <app-common/zap-generated/cluster-objects.h>
- #include <app/ConcreteAttributePath.h>
- #include <app/ConcreteCommandPath.h>
- #include <app/EventHeader.h>
- #include <app/MessageDef/StatusIB.h>
- #include <app/data-model/DecodableList.h>
- #include <commands/common/RemoteDataModelLogger.h>
- #include <lib/support/BytesToHex.h>
- class DataModelLogger
- {
- public:
- static CHIP_ERROR LogAttribute(const chip::app::ConcreteDataAttributePath & path, chip::TLV::TLVReader * data);
- static CHIP_ERROR LogCommand(const chip::app::ConcreteCommandPath & path, chip::TLV::TLVReader * data);
- static CHIP_ERROR LogEvent(const chip::app::EventHeader & header, chip::TLV::TLVReader * data);
- private:
- static CHIP_ERROR LogValue(const char * label, size_t indent, bool value)
- {
- DataModelLogger::LogString(label, indent, value ? "TRUE" : "FALSE");
- return CHIP_NO_ERROR;
- }
- static CHIP_ERROR LogValue(const char * label, size_t indent, chip::CharSpan value)
- {
- DataModelLogger::LogString(label, indent, std::string(value.data(), value.size()));
- return CHIP_NO_ERROR;
- }
- static CHIP_ERROR LogValue(const char * label, size_t indent, chip::ByteSpan value)
- {
- // CHIP_CONFIG_LOG_MESSAGE_MAX_SIZE includes various prefixes we don't
- // control (timestamps, process ids, etc). Let's assume (hope?) that
- // those prefixes use up no more than half the total available space.
- // Right now it looks like the prefixes are 45 chars out of a 255 char
- // buffer.
- char buffer[CHIP_CONFIG_LOG_MESSAGE_MAX_SIZE / 2];
- size_t prefixSize = ComputePrefixSize(label, indent);
- if (prefixSize > ArraySize(buffer))
- {
- DataModelLogger::LogString("", 0, "Prefix is too long to fit in buffer");
- return CHIP_ERROR_INTERNAL;
- }
- const size_t availableSize = ArraySize(buffer) - prefixSize;
- // Each byte ends up as two hex characters.
- const size_t bytesPerLogCall = availableSize / 2;
- std::string labelStr(label);
- while (value.size() > bytesPerLogCall)
- {
- ReturnErrorOnFailure(
- chip::Encoding::BytesToUppercaseHexString(value.data(), bytesPerLogCall, &buffer[0], ArraySize(buffer)));
- LogString(labelStr, indent, buffer);
- value = value.SubSpan(bytesPerLogCall);
- // For the second and following lines, make it clear that they are
- // continuation lines by replacing the label with "....".
- labelStr.replace(labelStr.begin(), labelStr.end(), labelStr.size(), '.');
- }
- ReturnErrorOnFailure(chip::Encoding::BytesToUppercaseHexString(value.data(), value.size(), &buffer[0], ArraySize(buffer)));
- LogString(labelStr, indent, buffer);
- return CHIP_NO_ERROR;
- }
- template <typename X,
- typename std::enable_if_t<
- std::is_integral<X>::value && !std::is_same<std::remove_cv_t<std::remove_reference_t<X>>, bool>::value, int> = 0>
- static CHIP_ERROR LogValue(const char * label, size_t indent, X value)
- {
- DataModelLogger::LogString(label, indent, std::to_string(value));
- return CHIP_NO_ERROR;
- }
- template <typename X, typename std::enable_if_t<std::is_floating_point<X>::value, int> = 0>
- static CHIP_ERROR LogValue(const char * label, size_t indent, X value)
- {
- DataModelLogger::LogString(label, indent, std::to_string(value));
- return CHIP_NO_ERROR;
- }
- template <typename X, typename std::enable_if_t<std::is_enum<X>::value, int> = 0>
- static CHIP_ERROR LogValue(const char * label, size_t indent, X value)
- {
- return DataModelLogger::LogValue(label, indent, chip::to_underlying(value));
- }
- template <typename X>
- static CHIP_ERROR LogValue(const char * label, size_t indent, chip::BitFlags<X> value)
- {
- return DataModelLogger::LogValue(label, indent, value.Raw());
- }
- template <typename T>
- static CHIP_ERROR LogValue(const char * label, size_t indent, const chip::app::DataModel::DecodableList<T> & value)
- {
- size_t count = 0;
- ReturnErrorOnFailure(value.ComputeSize(&count));
- DataModelLogger::LogString(label, indent, std::to_string(count) + " entries");
- auto iter = value.begin();
- size_t i = 0;
- while (iter.Next())
- {
- ++i;
- std::string itemLabel = std::string("[") + std::to_string(i) + "]";
- ReturnErrorOnFailure(DataModelLogger::LogValue(itemLabel.c_str(), indent + 1, iter.GetValue()));
- }
- if (iter.GetStatus() != CHIP_NO_ERROR)
- {
- DataModelLogger::LogString(indent + 1, "List truncated due to invalid value");
- }
- return iter.GetStatus();
- }
- template <typename T>
- static CHIP_ERROR LogValue(const char * label, size_t indent, const chip::app::DataModel::Nullable<T> & value)
- {
- if (value.IsNull())
- {
- DataModelLogger::LogString(label, indent, "null");
- return CHIP_NO_ERROR;
- }
- return DataModelLogger::LogValue(label, indent, value.Value());
- }
- template <typename T>
- static CHIP_ERROR LogValue(const char * label, size_t indent, const chip::Optional<T> & value)
- {
- if (value.HasValue())
- {
- return DataModelLogger::LogValue(label, indent, value.Value());
- }
- return CHIP_NO_ERROR;
- }
- #include <zap-generated/cluster/logging/DataModelLogger.h>
- static void LogString(size_t indent, const std::string string) { LogString("", indent, string); }
- static void LogString(const std::string label, size_t indent, const std::string string)
- {
- std::string prefix = ComputePrefix(label, indent);
- ChipLogProgress(chipTool, "%s%s", prefix.c_str(), string.c_str());
- }
- private:
- static std::string ComputePrefix(const std::string label, size_t indent)
- {
- std::string prefix;
- for (size_t i = 0; i < indent; ++i)
- {
- prefix.append(" ");
- }
- if (label.size() > 0)
- {
- prefix.append(label);
- prefix.append(":");
- }
- prefix.append(" ");
- return prefix;
- }
- static size_t ComputePrefixSize(const std::string label, size_t indent) { return ComputePrefix(label, indent).size(); }
- };
|