Skip to content

Commit 91bfd46

Browse files
feat(logging): add LogLevel severity enum (1/6)
First block of the iceberg-cpp logging system. Introduces the severity level type the rest of the stack builds on: - LogLevel { kTrace, kDebug, kInfo, kWarn, kError, kCritical, kFatal, kOff }, ordered so `level >= threshold` is the enabled test; kOff is the max sentinel (disables all emission as a threshold, never an actual message level). - constexpr ToString() and case-insensitive LogLevelFromString() -> Result<LogLevel>, mirroring the CounterUnit pattern in src/iceberg/metrics/. Wires the new logging/ subdirectory and a logging_test target into BOTH the CMake and Meson builds (header install + test), so the two build systems stay at parity from the first block. Co-authored-by: Isaac
1 parent d3b02bb commit 91bfd46

9 files changed

Lines changed: 210 additions & 0 deletions

File tree

src/iceberg/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,7 @@ add_subdirectory(row)
239239
add_subdirectory(update)
240240
add_subdirectory(util)
241241
add_subdirectory(metrics)
242+
add_subdirectory(logging)
242243

243244
if(ICEBERG_BUILD_BUNDLE)
244245
set(ICEBERG_BUNDLE_SOURCES

src/iceberg/logging/CMakeLists.txt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one
2+
# or more contributor license agreements. See the NOTICE file
3+
# distributed with this work for additional information
4+
# regarding copyright ownership. The ASF licenses this file
5+
# to you under the Apache License, Version 2.0 (the
6+
# "License"); you may not use this file except in compliance
7+
# with the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
18+
iceberg_install_all_headers(iceberg/logging)

src/iceberg/logging/log_level.h

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
#pragma once
21+
22+
/// \file iceberg/logging/log_level.h
23+
/// \brief Severity levels for the logging system.
24+
25+
#include <string_view>
26+
#include <utility>
27+
28+
#include "iceberg/result.h"
29+
#include "iceberg/util/string_util.h"
30+
31+
namespace iceberg {
32+
33+
/// \brief Logging severity level, ordered from most to least verbose.
34+
///
35+
/// Levels are ordered so that `level >= threshold` is the enabled test.
36+
/// `kOff` is the maximum sentinel: as a threshold it disables all emission
37+
/// (it is never the level of an actual message).
38+
enum class LogLevel {
39+
kTrace,
40+
kDebug,
41+
kInfo,
42+
kWarn,
43+
kError,
44+
kCritical,
45+
kFatal,
46+
kOff,
47+
};
48+
49+
/// \brief String representation of a LogLevel.
50+
constexpr std::string_view ToString(LogLevel level) noexcept {
51+
switch (level) {
52+
case LogLevel::kTrace:
53+
return "trace";
54+
case LogLevel::kDebug:
55+
return "debug";
56+
case LogLevel::kInfo:
57+
return "info";
58+
case LogLevel::kWarn:
59+
return "warn";
60+
case LogLevel::kError:
61+
return "error";
62+
case LogLevel::kCritical:
63+
return "critical";
64+
case LogLevel::kFatal:
65+
return "fatal";
66+
case LogLevel::kOff:
67+
return "off";
68+
}
69+
std::unreachable();
70+
}
71+
72+
/// \brief Parse a LogLevel from a string (case-insensitive).
73+
///
74+
/// \param s The string to parse ("trace", "debug", "info", "warn", "error",
75+
/// "critical", "fatal", or "off").
76+
/// \return The LogLevel, or an InvalidArgument error if unrecognized.
77+
inline Result<LogLevel> LogLevelFromString(std::string_view s) {
78+
auto level = StringUtils::ToLower(s);
79+
if (level == "trace") return LogLevel::kTrace;
80+
if (level == "debug") return LogLevel::kDebug;
81+
if (level == "info") return LogLevel::kInfo;
82+
if (level == "warn") return LogLevel::kWarn;
83+
if (level == "error") return LogLevel::kError;
84+
if (level == "critical") return LogLevel::kCritical;
85+
if (level == "fatal") return LogLevel::kFatal;
86+
if (level == "off") return LogLevel::kOff;
87+
return InvalidArgument("Invalid log level: {}", s);
88+
}
89+
90+
} // namespace iceberg

src/iceberg/logging/meson.build

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one
2+
# or more contributor license agreements. See the NOTICE file
3+
# distributed with this work for additional information
4+
# regarding copyright ownership. The ASF licenses this file
5+
# to you under the Apache License, Version 2.0 (the
6+
# "License"); you may not use this file except in compliance
7+
# with the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
18+
install_headers(['log_level.h'], subdir: 'iceberg/logging')

src/iceberg/meson.build

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ configure_file(
3838
install_dir: get_option('includedir') / 'iceberg',
3939
)
4040

41+
subdir('logging')
42+
4143
iceberg_include_dir = include_directories('..')
4244
iceberg_sources = files(
4345
'arrow_c_data_guard_internal.cc',

src/iceberg/test/.meson.build.swp

20 KB
Binary file not shown.

src/iceberg/test/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,8 @@ add_iceberg_test(table_test
101101
table_test.cc
102102
table_update_test.cc)
103103

104+
add_iceberg_test(logging_test SOURCES log_level_test.cc)
105+
104106
add_iceberg_test(expression_test
105107
SOURCES
106108
aggregate_test.cc

src/iceberg/test/log_level_test.cc

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
#include "iceberg/logging/log_level.h"
21+
22+
#include <array>
23+
#include <string>
24+
25+
#include <gtest/gtest.h>
26+
27+
namespace iceberg {
28+
29+
namespace {
30+
31+
constexpr std::array<LogLevel, 8> kAllLevels = {
32+
LogLevel::kTrace, LogLevel::kDebug, LogLevel::kInfo, LogLevel::kWarn,
33+
LogLevel::kError, LogLevel::kCritical, LogLevel::kFatal, LogLevel::kOff};
34+
35+
} // namespace
36+
37+
TEST(LogLevelTest, ToStringCoversEveryLevel) {
38+
EXPECT_EQ(ToString(LogLevel::kTrace), "trace");
39+
EXPECT_EQ(ToString(LogLevel::kDebug), "debug");
40+
EXPECT_EQ(ToString(LogLevel::kInfo), "info");
41+
EXPECT_EQ(ToString(LogLevel::kWarn), "warn");
42+
EXPECT_EQ(ToString(LogLevel::kError), "error");
43+
EXPECT_EQ(ToString(LogLevel::kCritical), "critical");
44+
EXPECT_EQ(ToString(LogLevel::kFatal), "fatal");
45+
EXPECT_EQ(ToString(LogLevel::kOff), "off");
46+
}
47+
48+
TEST(LogLevelTest, FromStringRoundTrips) {
49+
for (LogLevel level : kAllLevels) {
50+
auto parsed = LogLevelFromString(ToString(level));
51+
ASSERT_TRUE(parsed.has_value()) << "failed to parse " << ToString(level);
52+
EXPECT_EQ(parsed.value(), level);
53+
}
54+
}
55+
56+
TEST(LogLevelTest, FromStringIsCaseInsensitive) {
57+
EXPECT_EQ(LogLevelFromString("WARN").value(), LogLevel::kWarn);
58+
EXPECT_EQ(LogLevelFromString("Warn").value(), LogLevel::kWarn);
59+
EXPECT_EQ(LogLevelFromString("CRITICAL").value(), LogLevel::kCritical);
60+
}
61+
62+
TEST(LogLevelTest, FromStringRejectsUnknown) {
63+
auto parsed = LogLevelFromString("verbose");
64+
ASSERT_FALSE(parsed.has_value());
65+
EXPECT_EQ(parsed.error().kind, ErrorKind::kInvalidArgument);
66+
}
67+
68+
TEST(LogLevelTest, OrderingIsMonotonicWithOffAsMaximum) {
69+
EXPECT_LT(LogLevel::kTrace, LogLevel::kDebug);
70+
EXPECT_LT(LogLevel::kDebug, LogLevel::kInfo);
71+
EXPECT_LT(LogLevel::kInfo, LogLevel::kWarn);
72+
EXPECT_LT(LogLevel::kWarn, LogLevel::kError);
73+
EXPECT_LT(LogLevel::kError, LogLevel::kCritical);
74+
EXPECT_LT(LogLevel::kCritical, LogLevel::kFatal);
75+
EXPECT_LT(LogLevel::kFatal, LogLevel::kOff);
76+
}
77+
78+
} // namespace iceberg

src/iceberg/test/meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ iceberg_tests = {
6060
'table_update_test.cc',
6161
),
6262
},
63+
'logging_test': {'sources': files('log_level_test.cc')},
6364
'expression_test': {
6465
'sources': files(
6566
'aggregate_test.cc',

0 commit comments

Comments
 (0)