Skip to content

Conversation

@sanikolaev
Copy link
Collaborator

@sanikolaev sanikolaev commented Nov 18, 2025

The fix separates logging timezone from time function timezone and improves timezone name detection:

  1. Separated logging and time function timezones:

    • g_hTimeZoneLocal (for logging): Always uses the actual system local timezone, determined by temporarily unsetting TZ before calling cctz::local_time_zone()
    • g_hTimeZone (for time functions like NOW(), CURTIME()): Respects TZ environment variable or timezone config setting if set, otherwise uses system local timezone
  2. Improved timezone name detection:

    • Added g_sTimeZoneName to cache explicitly set timezone names
    • Modified DetermineLocalTimeZoneName() to ignore TZ when detecting system timezone and added bUseSystemDir parameter to force using system directory (/usr/share/zoneinfo/) instead of Manticore's TZDIR
    • Enhanced GetTimeZoneName() to:
      • Return cached timezone name if explicitly set
      • Attempt to parse /etc/localtime symlink when cctz returns a file path or "UTC"
      • Fall back to UTC offset calculation (e.g., UTC+07, UTC+05:30) when timezone name cannot be determined
      • Return "UTC" instead of "UTC+0" for zero offset
  3. Added UTC offset calculation:

    • New GetUTCOffsetString() function calculates UTC offset from system time
    • Handles both whole-hour offsets (e.g., UTC+07) and half-hour offsets (e.g., UTC+05:30)
    • Returns "UTC" for zero offset

Key Changes

  • SetTimeZoneLocal(): Temporarily unsets TZ to get actual system timezone for logging, then restores it for time functions
  • DetermineLocalTimeZoneName(): Now ignores TZ and can use system directory when bUseSystemDir=true
  • GetTimeZoneName(): Enhanced to detect timezone names from /etc/localtime and provide UTC offset fallback
  • GetUTCOffsetString(): New helper function for UTC offset calculation

Logging now always uses the local time, no matter what TZ or searchd.timezone is set to. Example:

 ~/manticore_github/cache/linux-x86_64   logging_tz  docker run -it --rm \
  -v /etc/localtime:/etc/localtime:ro \
  -v /etc/timezone:/etc/timezone:ro \
  test-kit bash

WARNING: The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested
root@1766d0e85a2c:/#
root@1766d0e85a2c:/# date; searchd --stopwait > /dev/null 2>&1; rm /var/log/manticore/*.log; searchd 2>&1|grep timezone; sleep 1; mysql -P9306 -h0 -e "drop table if exists t; create table t; insert into t values(1); select time(now()) from t"; tail -n 1 /var/log/manticore/searchd.log /var/log/manticore/query.log
Tue Nov 18 17:31:09 +07 2025
rm: cannot remove '/var/log/manticore/*.log': No such file or directory
+-------------+
| time(now()) |
+-------------+
| 17:31:12    |
+-------------+
==> /var/log/manticore/searchd.log <==
[Tue Nov 18 17:31:11.993 2025] [47] [BUDDY]   extra:

==> /var/log/manticore/query.log <==
/* Tue Nov 18 17:31:12.796 2025 conn 5 (127.0.0.1:54826) real 0.024 wall 0.025 found 1 */ SELECT time(now()) FROM t;
root@1766d0e85a2c:/#
root@1766d0e85a2c:/# date; searchd --stopwait > /dev/null 2>&1; rm /var/log/manticore/*.log; TZ=Europe/Berlin searchd 2>&1|grep timezone; sleep 1; mysql -P9306 -h0 -e "drop table if exists t; create table t; insert into t values(1); select time(now()) from t"; tail -n 1 /var/log/manticore/searchd.log /var/log/manticore/query.log
Tue Nov 18 17:31:16 +07 2025
+-------------+
| time(now()) |
+-------------+
| 11:31:20    |
+-------------+
==> /var/log/manticore/searchd.log <==
[Tue Nov 18 17:31:19.558 2025] [134] [BUDDY]   extra:

==> /var/log/manticore/query.log <==
/* Tue Nov 18 17:31:20.353 2025 conn 5 (127.0.0.1:50510) real 0.018 wall 0.019 found 1 */ SELECT time(now()) FROM t;
root@1766d0e85a2c:/#
root@1766d0e85a2c:/# sed -i '$i timezone=America/New_York' /etc/manticoresearch/manticore.conf
root@1766d0e85a2c:/#
root@1766d0e85a2c:/# date; searchd --stopwait > /dev/null 2>&1; rm /var/log/manticore/*.log; searchd 2>&1|grep timezone; sleep 1; mysql -P9306 -h0 -e "drop table if exists t; create table t; insert into t values(1); select time(now()) from t"; tail -n 1 /var/log/manticore/searchd.log /var/log/manticore/query.log
Tue Nov 18 17:31:27 +07 2025
+-------------+
| time(now()) |
+-------------+
| 05:31:31    |
+-------------+
==> /var/log/manticore/searchd.log <==
[Tue Nov 18 17:31:31.076 2025] [231] [BUDDY]   extra:

==> /var/log/manticore/query.log <==
/* Tue Nov 18 17:31:31.868 2025 conn 5 (127.0.0.1:55702) real 0.019 wall 0.020 found 1 */ SELECT time(now()) FROM t;
root@1766d0e85a2c:/#
root@1766d0e85a2c:/# date; searchd --stopwait > /dev/null 2>&1; rm /var/log/manticore/*.log; TZ=Europe/Berlin searchd 2>&1|grep timezone; sleep 1; mysql -P9306 -h0 -e "drop table if exists t; create table t; insert into t values(1); select time(now()) from t"; tail -n 1 /var/log/manticore/searchd.log /var/log/manticore/query.log
Tue Nov 18 17:31:39 +07 2025
+-------------+
| time(now()) |
+-------------+
| 05:31:42    |
+-------------+
==> /var/log/manticore/searchd.log <==
[Tue Nov 18 17:31:41.653 2025] [316] [BUDDY]   extra:

==> /var/log/manticore/query.log <==
/* Tue Nov 18 17:31:42.417 2025 conn 5 (127.0.0.1:56836) real 0.018 wall 0.019 found 1 */ SELECT time(now()) FROM t;

Commands useful for manual testing:

docker run -it --rm \
  -v /etc/localtime:/etc/localtime:ro \
  -v /etc/timezone:/etc/timezone:ro \
  test-kit bash

date; searchd --stopwait > /dev/null 2>&1; rm /var/log/manticore/*.log; searchd 2>&1|grep timezone; sleep 1; mysql -P9306 -h0 -e "drop table if exists t; create table t; insert into t values(1); select time(now()) from t"; tail -n 1 /var/log/manticore/searchd.log /var/log/manticore/query.log; mysql -h0 -P9306 -e "show variables like 'timezone'\G" | grep Value

date; searchd --stopwait > /dev/null 2>&1; rm /var/log/manticore/*.log; TZ=Europe/Berlin searchd 2>&1|grep timezone; sleep 1; mysql -P9306 -h0 -e "drop table if exists t; create table t; insert into t values(1); select time(now()) from t"; tail -n 1 /var/log/manticore/searchd.log /var/log/manticore/query.log; mysql -h0 -P9306 -e "show variables like 'timezone'\G" | grep Value

sed -i '$i timezone=America/New_York' /etc/manticoresearch/manticore.conf

date; searchd --stopwait > /dev/null 2>&1; rm /var/log/manticore/*.log; searchd 2>&1|grep timezone; sleep 1; mysql -P9306 -h0 -e "drop table if exists t; create table t; insert into t values(1); select time(now()) from t"; tail -n 1 /var/log/manticore/searchd.log /var/log/manticore/query.log; mysql -h0 -P9306 -e "show variables like 'timezone'\G" | grep Value

date; searchd --stopwait > /dev/null 2>&1; rm /var/log/manticore/*.log; TZ=Europe/Berlin searchd 2>&1|grep timezone; sleep 1; mysql -P9306 -h0 -e "drop table if exists t; create table t; insert into t values(1); select time(now()) from t"; tail -n 1 /var/log/manticore/searchd.log /var/log/manticore/query.log; mysql -h0 -P9306 -e "show variables like 'timezone'\G" | grep Value


date; searchd --stopwait > /dev/null 2>&1; rm /var/log/manticore/*.log; TZ=Europe/Berlin searchd 2>&1|grep timezone; sleep 1; mysql -P9306 -h0 -e "set global timezone='Europe/Riga'; drop table if exists t; create table t; insert into t values(1); select time(now()) from t"; tail -n 1 /var/log/manticore/searchd.log /var/log/manticore/query.log; mysql -h0 -P9306 -e "show variables like 'timezone'\G" | grep Value

@sanikolaev sanikolaev requested a review from glookka November 18, 2025 10:38
@sanikolaev
Copy link
Collaborator Author

For comparison, here’s how it looked before the fix:

 ~/manticore_github/test   logging_tz  docker run -it --rm \
  -v /etc/localtime:/etc/localtime:ro \
  -v /etc/timezone:/etc/timezone:ro \
  ghcr.io/manticoresoftware/manticoresearch:test-kit-latest bash

WARNING: The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested
root@01aab5441cea:/# date; searchd --stopwait > /dev/null 2>&1; rm /var/log/manticore/*.log; searchd 2>&1|grep timezone; sleep 1; mysql -P9306 -h0 -e "drop table if exists t; create table t; insert into t values(1); select time(now()) from t"; tail -n 1 /var/log/manticore/searchd.log /var/log/manticore/query.log
Tue Nov 18 17:32:07 +07 2025
rm: cannot remove '/var/log/manticore/*.log': No such file or directory
+-------------+
| time(now()) |
+-------------+
| 10:32:08    |
+-------------+
==> /var/log/manticore/searchd.log <==
[Tue Nov 18 10:32:08.049 2025] [47] [BUDDY]   extra:

==> /var/log/manticore/query.log <==
/* Tue Nov 18 10:32:08.867 2025 conn 5 (127.0.0.1:57690) real 0.008 wall 0.008 found 1 */ SELECT time(now()) FROM t;
root@01aab5441cea:/#
root@01aab5441cea:/# date; searchd --stopwait > /dev/null 2>&1; rm /var/log/manticore/*.log; TZ=Europe/Berlin searchd 2>&1|grep timezone; sleep 1; mysql -P9306 -h0 -e "drop table if exists t; create table t; insert into t values(1); select time(now()) from t"; tail -n 1 /var/log/manticore/searchd.log /var/log/manticore/query.log
Tue Nov 18 17:32:20 +07 2025
+-------------+
| time(now()) |
+-------------+
| 11:32:22    |
+-------------+
==> /var/log/manticore/searchd.log <==
[Tue Nov 18 11:32:21.728 2025] [136] [BUDDY]   extra:

==> /var/log/manticore/query.log <==
/* Tue Nov 18 11:32:22.568 2025 conn 5 (127.0.0.1:51868) real 0.008 wall 0.008 found 1 */ SELECT time(now()) FROM t;
root@01aab5441cea:/#
root@01aab5441cea:/# sed -i '$i timezone=America/New_York' /etc/manticoresearch/manticore.conf
root@01aab5441cea:/#
root@01aab5441cea:/# date; searchd --stopwait > /dev/null 2>&1; rm /var/log/manticore/*.log; searchd 2>&1|grep timezone; sleep 1; mysql -P9306 -h0 -e "drop table if exists t; create table t; insert into t values(1); select time(now()) from t"; tail -n 1 /var/log/manticore/searchd.log /var/log/manticore/query.log
Tue Nov 18 17:32:38 +07 2025
+-------------+
| time(now()) |
+-------------+
| 05:32:41    |
+-------------+
==> /var/log/manticore/searchd.log <==
[Tue Nov 18 10:32:40.439 2025] [230] [BUDDY]   extra:

==> /var/log/manticore/query.log <==
/* Tue Nov 18 10:32:41.277 2025 conn 5 (127.0.0.1:53728) real 0.008 wall 0.008 found 1 */ SELECT time(now()) FROM t;
root@01aab5441cea:/#
root@01aab5441cea:/# date; searchd --stopwait > /dev/null 2>&1; rm /var/log/manticore/*.log; TZ=Europe/Berlin searchd 2>&1|grep timezone; sleep 1; mysql -P9306 -h0 -e "drop table if exists t; create table t; insert into t values(1); select time(now()) from t"; tail -n 1 /var/log/manticore/searchd.log /var/log/manticore/query.log
Tue Nov 18 17:32:53 +07 2025
+-------------+
| time(now()) |
+-------------+
| 05:32:55    |
+-------------+
==> /var/log/manticore/searchd.log <==
[Tue Nov 18 11:32:55.144 2025] [317] [BUDDY]   extra:

==> /var/log/manticore/query.log <==
/* Tue Nov 18 11:32:55.945 2025 conn 5 (127.0.0.1:48528) real 0.008 wall 0.008 found 1 */ SELECT time(now()) FROM t;

Copy link
Contributor

@glookka glookka left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see that tests fail, what's the point in reviewing?

- {"Variable_name":"timezone","Value":"UTC"},
+ {"Variable_name":"timezone","Value":"/etc/localtime"},

@sanikolaev
Copy link
Collaborator Author

The test may need an update because the UTC value is even more incorrect, e.g. with the latest version it works so:

root@25326c93d165:/# date
Tue Nov 18 19:57:37 +07 2025

root@25326c93d165:/# searchd
Manticore 0.0.0 7d3f43671@25111007 (columnar 8.1.0 e1522a2@25100213) (secondary 8.1.0 e1522a2@25100213) (knn 8.1.0 e1522a2@25100213) (embeddings 1.0.1)
Copyright (c) 2001-2016, Andrew Aksyonoff
Copyright (c) 2008-2016, Sphinx Technologies Inc (http://sphinxsearch.com)
Copyright (c) 2017-2025, Manticore Software LTD (https://manticoresearch.com)

[57:44.021] [28] using config file '/etc/manticoresearch/manticore.conf' (269 chars)...
starting daemon version '0.0.0 7d3f43671@25111007 (columnar 8.1.0 e1522a2@25100213) (secondary 8.1.0 e1522a2@25100213) (knn 8.1.0 e1522a2@25100213) (embeddings 1.0.1)' ...
listening on 127.0.0.1:9312 for sphinx and http(s)
listening on 127.0.0.1:9306 for mysql
listening on 127.0.0.1:9308 for sphinx and http(s)

root@25326c93d165:/# mysql -h0 -P9306 -e "show variables like 'timezone'\G" | grep Value
        Value: UTC

The local timezone has nothing to do with UTC, but SHOW VARIABLES says it's UTC.

But you're right. It's better to fix it first and then review all at once.

@glookka
Copy link
Contributor

glookka commented Nov 18, 2025

The local timezone has nothing to do with UTC, but SHOW VARIABLES says it's UTC.

If it wasn't modified with config values or SET GLOBAL, it should show local time zone name. If it doesn't, it's a bug. If it shows '/etc/localtime' instead of a time zone name, it's a bug too.

@glookka
Copy link
Contributor

glookka commented Nov 18, 2025

I see that some pretty specific code was added (// If timezone name cannot be determined, calculate UTC offset as fallback). It seems that it was aimed at fixing some specific issue. What was that issue? What was the time zone name in the test and why couldn't it be determined?

@sanikolaev
Copy link
Collaborator Author

I see that some pretty specific code was added (// If timezone name cannot be determined, calculate UTC offset as fallback). It seems that it was aimed at fixing some specific issue. What was that issue? What was the time zone name in the test and why couldn't it be determined?

I'm working on improving the timezone.rec CLT test, which should make the behavior easier to understand.

@glookka
Copy link
Contributor

glookka commented Nov 18, 2025

I see that the original issue was updated and it seems that the problem is that the code couldn't detect that the time zone was set to EST and was using UTC. At the same time '/etc/localtime' contains UTC and $TZ is not set. But date returns EST time. Where does the system get the EST from?

@sanikolaev
Copy link
Collaborator Author

As we discussed, even though these changes seem to fix the issue, the implementation should use a different approach. I also committed the updated CLT test, which you can use as a reference. It passes with the changes in this PR and fails on the master branch.

Feel free to close this PR if you prefer to start a new one and not continue here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants