ICU-20593 Trace instrumentation for data loading.

- Adds hooks to utrace.h to record when ICU reads from locale data.
- Adds userguide page to document the new hooks.
diff --git a/.travis.yml b/.travis.yml
index 154e2e2..35251d5 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -51,7 +51,7 @@
       before_script:
         - mkdir build
         - cd build
-        - ../icu4c/source/runConfigureICU --enable-debug --disable-release Linux --prefix="${PREFIX}"
+        - ../icu4c/source/runConfigureICU --enable-debug --disable-release Linux --prefix="${PREFIX}" --enable-tracing
         - make -j2
       script:
         - make -j2 check
@@ -105,7 +105,7 @@
                   - clang-5.0
       before_script:
         - cd icu4c/source
-        - ./runConfigureICU --enable-debug --disable-release Linux --disable-renaming
+        - ./runConfigureICU --enable-debug --disable-release Linux --disable-renaming --enable-tracing
         - make -j2
       script:
         - make -j2 check
@@ -131,11 +131,11 @@
               packages:
                   - clang-5.0
       script:
-          - cd icu4c/source &&
-            ./runConfigureICU --enable-debug --disable-release Linux --disable-renaming &&
-            make -j2  &&
-            make -j2 -C test &&
-            make -j2 -C test/intltest check
+          - cd icu4c/source
+          - ./runConfigureICU --enable-debug --disable-release Linux --disable-renaming
+          - make -j2
+          - make -j2 -C test
+          - make -j2 -C test/intltest check
 
     # copyright scan / future linter
     - name: "lint"
diff --git a/docs/userguide/icu_data/buildtool.md b/docs/userguide/icu_data/buildtool.md
index 6078496..c6dedfd 100644
--- a/docs/userguide/icu_data/buildtool.md
+++ b/docs/userguide/icu_data/buildtool.md
@@ -518,6 +518,10 @@
 **Install jsonschema:** Install the `jsonschema` pip package to get warnings
 about problems with your filter file.
 
+**See what data is being used:** ICU is instrumented to allow you to trace
+which resources are used at runtime. This can help you determine what data you
+need to include. For more information, see [tracing.md](tracing.md).
+
 **Inspect data/rules.mk:** The Python script outputs the file *rules.mk*
 inside *iuc4c/source/data*. To see what is going to get built, you can inspect
 that file. First build ICU normally, and copy *rules.mk* to
diff --git a/docs/userguide/icu_data/tracing.md b/docs/userguide/icu_data/tracing.md
new file mode 100644
index 0000000..adc57a9
--- /dev/null
+++ b/docs/userguide/icu_data/tracing.md
@@ -0,0 +1,132 @@
+<!--
+© 2019 and later: Unicode, Inc. and others.
+License & terms of use: http://www.unicode.org/copyright.html
+-->
+
+Resource and Data Tracing
+=========================
+
+When building an [ICU data filter specification](buildtool.md), it is useful to
+see what resources are being used by your application so that you can select
+those resources and discard the others. This guide describes how to use
+*utrace.h* to inspect resource access in real time in ICU4C.
+
+**Note:** This feature is only available in ICU4C at this time. If you are
+interested in ICU4J, please see
+[ICU-20656](https://unicode-org.atlassian.net/browse/ICU-20656).
+
+## Quick Start
+
+First, you *must* have a copy of ICU4C configured with tracing enabled.
+
+    $ ./runConfigureICU Linux --enable-tracing
+
+The following program prints resource and data usages to standard out:
+
+```cpp
+#include "unicode/brkiter.h"
+#include "unicode/errorcode.h"
+#include "unicode/localpointer.h"
+#include "unicode/utrace.h"
+
+#include <iostream>
+
+static void U_CALLCONV traceData(
+        const void *context,
+        int32_t fnNumber,
+        int32_t level,
+        const char *fmt,
+        va_list args) {
+    char        buf[1000];
+    const char *fnName;
+
+    fnName = utrace_functionName(fnNumber);
+    utrace_vformat(buf, sizeof(buf), 0, fmt, args);
+    std::cout << fnName << " " << buf << std::endl;
+}
+
+int main() {
+    icu::ErrorCode status;
+
+    const void* context = nullptr;
+    utrace_setFunctions(context, nullptr, nullptr, traceData);
+    utrace_setLevel(UTRACE_VERBOSE);
+
+    // Create a new BreakIterator
+    icu::LocalPointer<icu::BreakIterator> brkitr(
+        icu::BreakIterator::createWordInstance("zh-CN", status));
+}
+```
+
+The following output is produced from this program:
+
+    FileTracer::traceOpenResFile icudt64l-brkitr/zh_CN.res
+    FileTracer::traceOpenResFile icudt64l-brkitr/zh.res
+    FileTracer::traceOpenResFile icudt64l-brkitr/root.res
+    ResourceTracer::trace (string) icudt64l-brkitr/root.res @ /boundaries/word
+    FileTracer::traceOpenDataFile icudt64l-brkitr/word.brk
+
+What this means:
+
+1. The BreakIterator constructor opened three resource files in the locale
+   fallback chain for zh_CN.
+2. One string was read from the resource bundle: the one at the resource path
+   "/boundaries/word" in brkitr/root.res.
+3. In addition, the binary data file brkitr/word.brk was opened.
+
+Based on that information, you can make a more informed decision when writing
+resource filter rules for this simple program.
+
+## Data Tracing API
+
+The `traceData` function shown above takes five arguments. The following two
+are most important for data tracing:
+
+- `fnNumber` indicates what type of data access this is.
+- `args` contains the details on which resources were accessed.
+
+**Important:** When reading from `args`, the strings are valid only within the
+scope of your `traceData` function. You should make copies of the strings if
+you intend to save them for further processing.
+
+### UTRACE_UDATA_RESOURCE
+
+UTRACE_UDATA_RESOURCE is used to indicate that a value inside of a resource
+bundle was read by ICU code.
+
+When `fnNumber` is `UTRACE_UDATA_RESOURCE`, there are three C-style strings in
+`args`:
+
+1. Data type; not relevant for the purpose of resource filtering.
+2. The internal path of the resource file from which the value was read.
+3. The path to the value within that resource file.
+
+To read each of these into different variables, you can write the code,
+
+```cpp
+const char* dataType = va_arg(args, const char*);
+const char* filePath = va_arg(args, const char*);
+const char* resPath = va_arg(args, const char*);
+```
+
+As stated above, you should copy the strings if you intend to save them. The
+pointers will not be valid after the tracing function returns.
+
+### UTRACE_UDATA_DATA_FILE
+
+UTRACE_UDATA_DATA_FILE is used to indicate that a non-resource-bundle binary
+data file was opened by ICU code. Such files are used for break iteration,
+conversion, confusables, and a handful of other ICU services.
+
+When `fnNumber` is `UTRACE_UDATA_DATA_FILE`, there is just one C string in
+`args`: the internal path of the data file that was opened.
+
+### UTRACE_UDATA_RES_FILE
+
+UTRACE_UDATA_RES_FILE is used to indicate that a binary resource bundle file
+was opened by ICU code. This can be helpful to debug locale fallbacks. For the
+purposes of making your ICU data filter, the specific resource paths provided
+by UTRACE_UDATA_RESOURCE are more precise and useful.
+
+When `fnNumber` is `UTRACE_UDATA_RES_FILE`, there is just one C string in
+`args`: the internal path of the resource file that was opened.
diff --git a/icu4c/source/common/Makefile.in b/icu4c/source/common/Makefile.in
index e663cb8..79e371b 100644
--- a/icu4c/source/common/Makefile.in
+++ b/icu4c/source/common/Makefile.in
@@ -115,7 +115,8 @@
 sharedobject.o simpleformatter.o unifiedcache.o uloc_keytype.o \
 ubiditransform.o \
 pluralmap.o \
-static_unicode_sets.o
+static_unicode_sets.o \
+restrace.o
 
 ## Header files to install
 HEADERS = $(srcdir)/unicode/*.h
diff --git a/icu4c/source/common/common.vcxproj b/icu4c/source/common/common.vcxproj
index 6b06b3d..02c88e24 100644
--- a/icu4c/source/common/common.vcxproj
+++ b/icu4c/source/common/common.vcxproj
@@ -339,6 +339,7 @@
     <ClCompile Include="utext.cpp" />
     <ClCompile Include="utf_impl.cpp" />
     <ClCompile Include="static_unicode_sets.cpp" />
+    <ClCompile Include="restrace.cpp" />
     <ClInclude Include="localsvc.h" />
     <ClInclude Include="msvcres.h" />
     <ClInclude Include="pluralmap.h" />
@@ -448,6 +449,7 @@
     <ClInclude Include="static_unicode_sets.h" />
     <ClInclude Include="capi_helper.h" />
     <ClInclude Include="unicode\localebuilder.h" />
+    <ClInclude Include="restrace.h" />
   </ItemGroup>
   <ItemGroup>
     <ResourceCompile Include="common.rc" />
diff --git a/icu4c/source/common/common.vcxproj.filters b/icu4c/source/common/common.vcxproj.filters
index 4fe13d5..f1a7825 100644
--- a/icu4c/source/common/common.vcxproj.filters
+++ b/icu4c/source/common/common.vcxproj.filters
@@ -619,6 +619,9 @@
     <ClCompile Include="static_unicode_sets.cpp">
       <Filter>formatting</Filter>
     </ClCompile>
+    <ClCompile Include="restrace.cpp">
+      <Filter>data &amp; memory</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="ubidi_props.h">
@@ -954,9 +957,12 @@
     <ClInclude Include="static_unicode_sets.h">
       <Filter>formatting</Filter>
     </ClInclude>
-    <CustomBuild Include="capi_helper.h">
+    <ClInclude Include="capi_helper.h">
       <Filter>data &amp; memory</Filter>
-    </CustomBuild>
+    </ClInclude>
+    <ClInclude Include="restrace.h">
+      <Filter>data &amp; memory</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ResourceCompile Include="common.rc">
diff --git a/icu4c/source/common/common_uwp.vcxproj b/icu4c/source/common/common_uwp.vcxproj
index 94169ce..260e460 100644
--- a/icu4c/source/common/common_uwp.vcxproj
+++ b/icu4c/source/common/common_uwp.vcxproj
@@ -465,6 +465,7 @@
     <ClCompile Include="utext.cpp" />
     <ClCompile Include="utf_impl.cpp" />
     <ClCompile Include="static_unicode_sets.cpp" />
+    <ClCompile Include="restrace.cpp" />
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="localsvc.h" />
@@ -575,6 +576,7 @@
     <ClInclude Include="static_unicode_sets.h" />
     <ClInclude Include="capi_helper.h" />
     <ClInclude Include="unicode\localebuilder.h" />
+    <ClInclude Include="restrace.h" />
   </ItemGroup>
   <ItemGroup>
     <ResourceCompile Include="common.rc" />
diff --git a/icu4c/source/common/resource.h b/icu4c/source/common/resource.h
index 3dbff78..ee93d41 100644
--- a/icu4c/source/common/resource.h
+++ b/icu4c/source/common/resource.h
@@ -28,6 +28,7 @@
 #include "unicode/utypes.h"
 #include "unicode/unistr.h"
 #include "unicode/ures.h"
+#include "restrace.h"
 
 struct ResourceData;
 
@@ -47,8 +48,10 @@
     ResourceArray() : items16(NULL), items32(NULL), length(0) {}
 
     /** Only for implementation use. @internal */
-    ResourceArray(const uint16_t *i16, const uint32_t *i32, int32_t len) :
-            items16(i16), items32(i32), length(len) {}
+    ResourceArray(const uint16_t *i16, const uint32_t *i32, int32_t len,
+                  const ResourceTracer& traceInfo) :
+            items16(i16), items32(i32), length(len),
+            fTraceInfo(traceInfo) {}
 
     /**
      * @return The number of items in the array resource.
@@ -68,6 +71,7 @@
     const uint16_t *items16;
     const uint32_t *items32;
     int32_t length;
+    ResourceTracer fTraceInfo;
 };
 
 /**
@@ -80,8 +84,10 @@
 
     /** Only for implementation use. @internal */
     ResourceTable(const uint16_t *k16, const int32_t *k32,
-                  const uint16_t *i16, const uint32_t *i32, int32_t len) :
-            keys16(k16), keys32(k32), items16(i16), items32(i32), length(len) {}
+                  const uint16_t *i16, const uint32_t *i32, int32_t len,
+                  const ResourceTracer& traceInfo) :
+            keys16(k16), keys32(k32), items16(i16), items32(i32), length(len),
+            fTraceInfo(traceInfo) {}
 
     /**
      * @return The number of items in the array resource.
@@ -101,6 +107,7 @@
     const uint16_t *items16;
     const uint32_t *items32;
     int32_t length;
+    ResourceTracer fTraceInfo;
 };
 
 /**
diff --git a/icu4c/source/common/restrace.cpp b/icu4c/source/common/restrace.cpp
new file mode 100644
index 0000000..2ab8241
--- /dev/null
+++ b/icu4c/source/common/restrace.cpp
@@ -0,0 +1,111 @@
+// © 2019 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
+
+#include "unicode/utypes.h"
+
+#if U_ENABLE_TRACING
+
+#include "restrace.h"
+#include "charstr.h"
+#include "cstring.h"
+#include "utracimp.h"
+#include "uresimp.h"
+#include "uassert.h"
+#include "util.h"
+
+U_NAMESPACE_BEGIN
+
+ResourceTracer::~ResourceTracer() = default;
+
+void ResourceTracer::trace(const char* resType) const {
+    U_ASSERT(fResB || fParent);
+    UTRACE_ENTRY(UTRACE_UDATA_RESOURCE);
+    UErrorCode status = U_ZERO_ERROR;
+
+    icu::CharString filePath;
+    getFilePath(filePath, status);
+
+    icu::CharString resPath;
+    getResPath(resPath, status);
+
+    UTRACE_DATA3(UTRACE_VERBOSE, "(%s) %s @ %s",
+        resType,
+        filePath.data(),
+        resPath.data());
+    UTRACE_EXIT_STATUS(status);
+}
+
+void ResourceTracer::getFilePath(CharString& output, UErrorCode& status) const {
+    if (fResB) {
+        output.append(fResB->fData->fPath, status);
+        output.append('/', status);
+        output.append(fResB->fData->fName, status);
+        output.append(".res", status);
+    } else {
+        fParent->getFilePath(output, status);
+    }
+}
+
+void ResourceTracer::getResPath(CharString& output, UErrorCode& status) const {
+    if (fResB) {
+        output.append('/', status);
+        output.append(fResB->fResPath, status);
+        // removing the trailing /
+        U_ASSERT(output[output.length()-1] == '/');
+        output.truncate(output.length()-1);
+    } else {
+        fParent->getResPath(output, status);
+    }
+    if (fKey) {
+        output.append('/', status);
+        output.append(fKey, status);
+    }
+    if (fIndex != -1) {
+        output.append('[', status);
+        UnicodeString indexString;
+        ICU_Utility::appendNumber(indexString, fIndex);
+        output.appendInvariantChars(indexString, status);
+        output.append(']', status);
+    }
+}
+
+void FileTracer::traceOpen(const char* path, const char* type, const char* name) {
+    if (uprv_strcmp(type, "res") == 0) {
+        traceOpenResFile(path, name);
+    } else {
+        traceOpenDataFile(path, type, name);
+    }
+}
+
+void FileTracer::traceOpenDataFile(const char* path, const char* type, const char* name) {
+    UTRACE_ENTRY(UTRACE_UDATA_DATA_FILE);
+    UErrorCode status = U_ZERO_ERROR;
+
+    icu::CharString filePath;
+    filePath.append(path, status);
+    filePath.append('/', status);
+    filePath.append(name, status);
+    filePath.append('.', status);
+    filePath.append(type, status);
+
+    UTRACE_DATA1(UTRACE_VERBOSE, "%s", filePath.data());
+    UTRACE_EXIT_STATUS(status);
+}
+
+void FileTracer::traceOpenResFile(const char* path, const char* name) {
+    UTRACE_ENTRY(UTRACE_UDATA_RES_FILE);
+    UErrorCode status = U_ZERO_ERROR;
+
+    icu::CharString filePath;
+    filePath.append(path, status);
+    filePath.append('/', status);
+    filePath.append(name, status);
+    filePath.append(".res", status);
+
+    UTRACE_DATA1(UTRACE_VERBOSE, "%s", filePath.data());
+    UTRACE_EXIT_STATUS(status);
+}
+
+U_NAMESPACE_END
+
+#endif // U_ENABLE_TRACING
diff --git a/icu4c/source/common/restrace.h b/icu4c/source/common/restrace.h
new file mode 100644
index 0000000..a8af919
--- /dev/null
+++ b/icu4c/source/common/restrace.h
@@ -0,0 +1,132 @@
+// © 2019 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
+
+#ifndef __RESTRACE_H__
+#define __RESTRACE_H__
+
+#include "unicode/utypes.h"
+
+#if U_ENABLE_TRACING
+
+struct UResourceBundle;
+
+U_NAMESPACE_BEGIN
+
+class CharString;
+
+/**
+ * Instances of this class store information used to trace reads from resource
+ * bundles when ICU is built with --enable-tracing.
+ *
+ * All arguments of type const UResourceBundle*, const char*, and
+ * const ResourceTracer& are stored as pointers. The caller must retain
+ * ownership for the lifetime of this ResourceTracer.
+ *
+ * Exported as U_COMMON_API for Windows because it is a value field
+ * in other exported types.
+ */
+class U_COMMON_API ResourceTracer {
+public:
+    ResourceTracer() :
+        fResB(nullptr),
+        fParent(nullptr),
+        fKey(nullptr),
+        fIndex(-1) {}
+
+    ResourceTracer(const UResourceBundle* resB) :
+        fResB(resB),
+        fParent(nullptr),
+        fKey(nullptr),
+        fIndex(-1) {}
+
+    ResourceTracer(const UResourceBundle* resB, const char* key) :
+        fResB(resB),
+        fParent(nullptr),
+        fKey(key),
+        fIndex(-1) {}
+
+    ResourceTracer(const UResourceBundle* resB, int32_t index) :
+        fResB(resB),
+        fParent(nullptr),
+        fKey(nullptr),
+        fIndex(index) {}
+
+    ResourceTracer(const ResourceTracer& parent, const char* key) :
+        fResB(nullptr),
+        fParent(&parent),
+        fKey(key),
+        fIndex(-1) {}
+
+    ResourceTracer(const ResourceTracer& parent, int32_t index) :
+        fResB(nullptr),
+        fParent(&parent),
+        fKey(nullptr),
+        fIndex(index) {}
+
+    ~ResourceTracer();
+
+    void trace(const char* type) const;
+
+private:
+    const UResourceBundle* fResB;
+    const ResourceTracer* fParent;
+    const char* fKey;
+    int32_t fIndex;
+
+    void getFilePath(CharString& output, UErrorCode& status) const;
+
+    void getResPath(CharString& output, UErrorCode& status) const;
+};
+
+/**
+ * This class provides methods to trace data file reads when ICU is built
+ * with --enable-tracing.
+ */
+class FileTracer {
+public:
+    static void traceOpen(const char* path, const char* type, const char* name);
+
+private:
+    static void traceOpenDataFile(const char* path, const char* type, const char* name);
+    static void traceOpenResFile(const char* path, const char* name);
+};
+
+U_NAMESPACE_END
+
+#else // U_ENABLE_TRACING
+
+U_NAMESPACE_BEGIN
+
+/**
+ * Default trivial implementation when --enable-tracing is not used.
+ */
+class U_COMMON_API ResourceTracer {
+public:
+    ResourceTracer() {}
+
+    ResourceTracer(const void*) {}
+
+    ResourceTracer(const void*, const char*) {}
+
+    ResourceTracer(const void*, int32_t) {}
+
+    ResourceTracer(const ResourceTracer&, const char*) {}
+
+    ResourceTracer(const ResourceTracer&, int32_t) {}
+
+    void trace(const char*) const {}
+};
+
+/**
+ * Default trivial implementation when --enable-tracing is not used.
+ */
+class FileTracer {
+public:
+    static void traceOpen(const char*, const char*, const char*) {}
+};
+
+U_NAMESPACE_END
+
+#endif // U_ENABLE_TRACING
+
+#endif //__RESTRACE_H__
diff --git a/icu4c/source/common/udata.cpp b/icu4c/source/common/udata.cpp
index bf7025a..9a2be4b 100644
--- a/icu4c/source/common/udata.cpp
+++ b/icu4c/source/common/udata.cpp
@@ -33,6 +33,7 @@
 #include "cstring.h"
 #include "mutex.h"
 #include "putilimp.h"
+#include "restrace.h"
 #include "uassert.h"
 #include "ucln_cmn.h"
 #include "ucmndata.h"
@@ -1168,6 +1169,9 @@
     UBool               isICUData = FALSE;
 
 
+    FileTracer::traceOpen(path, type, name);
+
+
     /* Is this path ICU data? */
     if(path == NULL ||
        !strcmp(path, U_ICUDATA_ALIAS) ||  /* "ICUDATA" */
diff --git a/icu4c/source/common/unicode/utrace.h b/icu4c/source/common/unicode/utrace.h
index 6626978..412e11a 100644
--- a/icu4c/source/common/unicode/utrace.h
+++ b/icu4c/source/common/unicode/utrace.h
@@ -66,6 +66,7 @@
     UTRACE_FUNCTION_START=0,
     UTRACE_U_INIT=UTRACE_FUNCTION_START,
     UTRACE_U_CLEANUP,
+
 #ifndef U_HIDE_DEPRECATED_API
     /**
      * One more than the highest normal collation trace location.
@@ -83,6 +84,7 @@
     UTRACE_UCNV_FLUSH_CACHE,
     UTRACE_UCNV_LOAD,
     UTRACE_UCNV_UNLOAD,
+
 #ifndef U_HIDE_DEPRECATED_API
     /**
      * One more than the highest normal collation trace location.
@@ -101,13 +103,55 @@
     UTRACE_UCOL_STRCOLLITER,
     UTRACE_UCOL_OPEN_FROM_SHORT_STRING,
     UTRACE_UCOL_STRCOLLUTF8, /**< @stable ICU 50 */
+
 #ifndef U_HIDE_DEPRECATED_API
     /**
      * One more than the highest normal collation trace location.
      * @deprecated ICU 58 The numeric value may change over time, see ICU ticket #12420.
      */
-    UTRACE_COLLATION_LIMIT
+    UTRACE_COLLATION_LIMIT,
 #endif  // U_HIDE_DEPRECATED_API
+
+#ifndef U_HIDE_DRAFT_API
+
+    /**
+     * The lowest resource/data location.
+     * @draft ICU 65
+     */
+    UTRACE_RES_DATA_START=0x3000,
+
+    /**
+     * Indicates that a value was read from a resource bundle. Provides three
+     * C-style strings to UTraceData: type, file name, and resource path. The
+     * type is "string", "binary", "intvector", "int", or "uint".
+     * @draft ICU 65
+     */
+    UTRACE_UDATA_RESOURCE=UTRACE_RES_DATA_START,
+
+    /**
+     * Indicates that a value was read from a resource bundle. Provides one
+     * C-style string to UTraceData: file name.
+     * @draft ICU 65
+     */
+    UTRACE_UDATA_DATA_FILE,
+
+    /**
+     * Indicates that a value was read from a resource bundle. Provides one
+     * C-style string to UTraceData: file name.
+     * @draft ICU 65
+     */
+    UTRACE_UDATA_RES_FILE,
+
+#endif  // U_HIDE_DRAFT_API
+
+#ifndef U_HIDE_INTERNAL_API
+    /**
+     * One more than the highest normal resource/data trace location.
+     * @internal The numeric value may change over time, see ICU ticket #12420.
+     */
+    UTRACE_RES_DATA_LIMIT,
+#endif  // U_HIDE_INTERNAL_API
+
 } UTraceFunctionNumber;
 
 /**
diff --git a/icu4c/source/common/uresbund.cpp b/icu4c/source/common/uresbund.cpp
index 57d133e..b8688aa 100644
--- a/icu4c/source/common/uresbund.cpp
+++ b/icu4c/source/common/uresbund.cpp
@@ -392,7 +392,8 @@
                 /* We'll try to get alias string from the bundle */
                 aliasres = res_getResource(&(r->fData), "%%ALIAS");
                 if (aliasres != RES_BOGUS) {
-                    const UChar *alias = res_getString(&(r->fData), aliasres, &aliasLen);
+                    // No tracing: called during initial data loading
+                    const UChar *alias = res_getStringNoTrace(&(r->fData), aliasres, &aliasLen);
                     if(alias != NULL && aliasLen > 0) { /* if there is actual alias - unload and load new data */
                         u_UCharsToChars(alias, aliasName, aliasLen+1);
                         r->fAlias = init_entry(aliasName, path, status);
@@ -533,7 +534,8 @@
         Resource parentRes = res_getResource(&t1->fData, "%%Parent");
         if (parentRes != RES_BOGUS) {  // An explicit parent was found.
             int32_t parentLocaleLen = 0;
-            const UChar *parentLocaleName = res_getString(&(t1->fData), parentRes, &parentLocaleLen);
+            // No tracing: called during initial data loading
+            const UChar *parentLocaleName = res_getStringNoTrace(&(t1->fData), parentRes, &parentLocaleLen);
             if(parentLocaleName != NULL && 0 < parentLocaleLen && parentLocaleLen < nameCapacity) {
                 u_UCharsToChars(parentLocaleName, name, parentLocaleLen + 1);
                 if (uprv_strcmp(name, kRootLocaleName) == 0) {
@@ -1291,7 +1293,7 @@
         *status = U_ILLEGAL_ARGUMENT_ERROR;
         return NULL;
     }
-    s = res_getString(&(resB->fResData), resB->fRes, len);
+    s = res_getString({resB}, &(resB->fResData), resB->fRes, len);
     if (s == NULL) {
         *status = U_RESOURCE_TYPE_MISMATCH;
     }
@@ -1380,7 +1382,7 @@
     *status = U_ILLEGAL_ARGUMENT_ERROR;
     return NULL;
   }
-  p = res_getBinary(&(resB->fResData), resB->fRes, len);
+  p = res_getBinary({resB}, &(resB->fResData), resB->fRes, len);
   if (p == NULL) {
     *status = U_RESOURCE_TYPE_MISMATCH;
   }
@@ -1397,7 +1399,7 @@
     *status = U_ILLEGAL_ARGUMENT_ERROR;
     return NULL;
   }
-  p = res_getIntVector(&(resB->fResData), resB->fRes, len);
+  p = res_getIntVector({resB}, &(resB->fResData), resB->fRes, len);
   if (p == NULL) {
     *status = U_RESOURCE_TYPE_MISMATCH;
   }
@@ -1418,7 +1420,7 @@
     *status = U_RESOURCE_TYPE_MISMATCH;
     return 0xffffffff;
   }
-  return RES_GET_INT(resB->fRes);
+  return res_getInt({resB}, resB->fRes);
 }
 
 U_CAPI uint32_t U_EXPORT2 ures_getUInt(const UResourceBundle* resB, UErrorCode *status) {
@@ -1433,7 +1435,7 @@
     *status = U_RESOURCE_TYPE_MISMATCH;
     return 0xffffffff;
   }
-  return RES_GET_UINT(resB->fRes);
+  return res_getUInt({resB}, resB->fRes);
 }
 
 U_CAPI UResType U_EXPORT2 ures_getType(const UResourceBundle *resB) {
@@ -1444,10 +1446,18 @@
 }
 
 U_CAPI const char * U_EXPORT2 ures_getKey(const UResourceBundle *resB) {
+  //
+  // TODO: Trace ures_getKey? I guess not usually.
+  //
+  // We usually get the key string to decide whether we want the value, or to
+  // make a key-value pair. Tracing the value should suffice.
+  //
+  // However, I believe we have some data (e.g., in res_index) where the key
+  // strings are the data. Tracing the enclosing table should suffice.
+  //
   if(resB == NULL) {
     return NULL;
   }
-  
   return(resB->fKey);
 }
 
@@ -1467,7 +1477,7 @@
     ures_close(tempRes);
     return result;
   } else {
-    return res_getString(&(resB->fResData), r, len); 
+    return res_getString({resB, sIndex}, &(resB->fResData), r, len); 
   }
 }
 
@@ -1503,7 +1513,7 @@
     switch(RES_GET_TYPE(resB->fRes)) {
     case URES_STRING:
     case URES_STRING_V2:
-      return res_getString(&(resB->fResData), resB->fRes, len); 
+      return res_getString({resB}, &(resB->fResData), resB->fRes, len);
     case URES_TABLE:
     case URES_TABLE16:
     case URES_TABLE32:
@@ -1648,7 +1658,7 @@
         switch(RES_GET_TYPE(resB->fRes)) {
         case URES_STRING:
         case URES_STRING_V2:
-            return res_getString(&(resB->fResData), resB->fRes, len);
+            return res_getString({resB}, &(resB->fResData), resB->fRes, len);
         case URES_TABLE:
         case URES_TABLE16:
         case URES_TABLE32:
@@ -1943,7 +1953,7 @@
     value.pResData = &bundle->fResData;
     UResourceDataEntry *parentEntry = bundle->fData->fParent;
     UBool hasParent = parentEntry != NULL && U_SUCCESS(parentEntry->fBogus);
-    value.setResource(bundle->fRes);
+    value.setResource(bundle->fRes, ResourceTracer(bundle));
     sink.put(bundle->fKey, value, !hasParent, errorCode);
     if (hasParent) {
         // We might try to query the sink whether
@@ -2095,7 +2105,7 @@
                     switch (RES_GET_TYPE(res)) {
                     case URES_STRING:
                     case URES_STRING_V2:
-                        return res_getString(rd, res, len);
+                        return res_getString({resB, key}, rd, res, len);
                     case URES_ALIAS:
                       {
                         const UChar* result = 0;
@@ -2117,7 +2127,7 @@
             switch (RES_GET_TYPE(res)) {
             case URES_STRING:
             case URES_STRING_V2:
-                return res_getString(&(resB->fResData), res, len);
+                return res_getString({resB, key}, &(resB->fResData), res, len);
             case URES_ALIAS:
               {
                 const UChar* result = 0;
@@ -2138,6 +2148,7 @@
         /* here should go a first attempt to locate the key using index table */
         const ResourceData *rd = getFallbackData(resB, &key, &realData, &res, status);
         if(U_SUCCESS(*status)) {
+            // TODO: Tracing
             return res_getString(rd, res, len);
         } else {
             *status = U_MISSING_RESOURCE_ERROR;
diff --git a/icu4c/source/common/uresdata.cpp b/icu4c/source/common/uresdata.cpp
index 8bcb9ab..ce04142 100644
--- a/icu4c/source/common/uresdata.cpp
+++ b/icu4c/source/common/uresdata.cpp
@@ -33,6 +33,7 @@
 #include "uinvchar.h"
 #include "uresdata.h"
 #include "uresimp.h"
+#include "utracimp.h"
 
 /*
  * Resource access helpers
@@ -307,7 +308,7 @@
 }
 
 U_CAPI const UChar * U_EXPORT2
-res_getString(const ResourceData *pResData, Resource res, int32_t *pLength) {
+res_getStringNoTrace(const ResourceData *pResData, Resource res, int32_t *pLength) {
     const UChar *p;
     uint32_t offset=RES_GET_OFFSET(res);
     int32_t length;
@@ -402,7 +403,8 @@
     }
     for(int32_t i = 0; i < length; ++i) {
         int32_t sLength;
-        const UChar *s = res_getString(pResData, array.internalGetResource(pResData, i), &sLength);
+        // No tracing: handled by the caller
+        const UChar *s = res_getStringNoTrace(pResData, array.internalGetResource(pResData, i), &sLength);
         if(s == NULL) {
             errorCode = U_RESOURCE_TYPE_MISMATCH;
             return 0;
@@ -434,7 +436,7 @@
 }
 
 U_CAPI const uint8_t * U_EXPORT2
-res_getBinary(const ResourceData *pResData, Resource res, int32_t *pLength) {
+res_getBinaryNoTrace(const ResourceData *pResData, Resource res, int32_t *pLength) {
     const uint8_t *p;
     uint32_t offset=RES_GET_OFFSET(res);
     int32_t length;
@@ -454,7 +456,7 @@
 
 
 U_CAPI const int32_t * U_EXPORT2
-res_getIntVector(const ResourceData *pResData, Resource res, int32_t *pLength) {
+res_getIntVectorNoTrace(const ResourceData *pResData, Resource res, int32_t *pLength) {
     const int32_t *p;
     uint32_t offset=RES_GET_OFFSET(res);
     int32_t length;
@@ -507,7 +509,7 @@
     if(U_FAILURE(errorCode)) {
         return NULL;
     }
-    const UChar *s = res_getString(pResData, res, &length);
+    const UChar *s = res_getString(fTraceInfo, pResData, res, &length);
     if(s == NULL) {
         errorCode = U_RESOURCE_TYPE_MISMATCH;
     }
@@ -532,7 +534,7 @@
     if(RES_GET_TYPE(res) != URES_INT) {
         errorCode = U_RESOURCE_TYPE_MISMATCH;
     }
-    return RES_GET_INT(res);
+    return res_getInt(fTraceInfo, res);
 }
 
 uint32_t ResourceDataValue::getUInt(UErrorCode &errorCode) const {
@@ -542,14 +544,14 @@
     if(RES_GET_TYPE(res) != URES_INT) {
         errorCode = U_RESOURCE_TYPE_MISMATCH;
     }
-    return RES_GET_UINT(res);
+    return res_getUInt(fTraceInfo, res);
 }
 
 const int32_t *ResourceDataValue::getIntVector(int32_t &length, UErrorCode &errorCode) const {
     if(U_FAILURE(errorCode)) {
         return NULL;
     }
-    const int32_t *iv = res_getIntVector(pResData, res, &length);
+    const int32_t *iv = res_getIntVector(fTraceInfo, pResData, res, &length);
     if(iv == NULL) {
         errorCode = U_RESOURCE_TYPE_MISMATCH;
     }
@@ -560,7 +562,7 @@
     if(U_FAILURE(errorCode)) {
         return NULL;
     }
-    const uint8_t *b = res_getBinary(pResData, res, &length);
+    const uint8_t *b = res_getBinary(fTraceInfo, pResData, res, &length);
     if(b == NULL) {
         errorCode = U_RESOURCE_TYPE_MISMATCH;
     }
@@ -590,7 +592,7 @@
         errorCode = U_RESOURCE_TYPE_MISMATCH;
         return ResourceArray();
     }
-    return ResourceArray(items16, items32, length);
+    return ResourceArray(items16, items32, length, fTraceInfo);
 }
 
 ResourceTable ResourceDataValue::getTable(UErrorCode &errorCode) const {
@@ -627,7 +629,7 @@
         errorCode = U_RESOURCE_TYPE_MISMATCH;
         return ResourceTable();
     }
-    return ResourceTable(keys16, keys32, items16, items32, length);
+    return ResourceTable(keys16, keys32, items16, items32, length, fTraceInfo);
 }
 
 UBool ResourceDataValue::isNoInheritanceMarker() const {
@@ -656,7 +658,7 @@
         return 1;
     }
     int32_t sLength;
-    const UChar *s = res_getString(pResData, res, &sLength);
+    const UChar *s = res_getString(fTraceInfo, pResData, res, &sLength);
     if(s != NULL) {
         dest[0].setTo(TRUE, s, sLength);
         return 1;
@@ -671,7 +673,7 @@
         return us;
     }
     int32_t sLength;
-    const UChar *s = res_getString(pResData, res, &sLength);
+    const UChar *s = res_getString(fTraceInfo, pResData, res, &sLength);
     if(s != NULL) {
         us.setTo(TRUE, s, sLength);
         return us;
@@ -681,7 +683,8 @@
         return us;
     }
     if(array.getSize() > 0) {
-        s = res_getString(pResData, array.internalGetResource(pResData, 0), &sLength);
+        // Tracing is already performed above (unimportant for trace that this is an array)
+        s = res_getStringNoTrace(pResData, array.internalGetResource(pResData, 0), &sLength);
         if(s != NULL) {
             us.setTo(TRUE, s, sLength);
             return us;
@@ -829,7 +832,11 @@
         } else {
             res = items32[i];
         }
-        rdValue.setResource(res);
+        // Note: the ResourceTracer keeps a reference to the field of this
+        // ResourceTable. This is OK because the ResourceTable should remain
+        // alive for the duration that fields are being read from it
+        // (including nested fields).
+        rdValue.setResource(res, ResourceTracer(fTraceInfo, key));
         return TRUE;
     }
     return FALSE;
@@ -875,7 +882,13 @@
 UBool icu::ResourceArray::getValue(int32_t i, icu::ResourceValue &value) const {
     if(0 <= i && i < length) {
         icu::ResourceDataValue &rdValue = static_cast<icu::ResourceDataValue &>(value);
-        rdValue.setResource(internalGetResource(rdValue.pResData, i));
+        // Note: the ResourceTracer keeps a reference to the field of this
+        // ResourceArray. This is OK because the ResourceArray should remain
+        // alive for the duration that fields are being read from it
+        // (including nested fields).
+        rdValue.setResource(
+            internalGetResource(rdValue.pResData, i),
+            ResourceTracer(fTraceInfo, i));
         return TRUE;
     }
     return FALSE;
diff --git a/icu4c/source/common/uresdata.h b/icu4c/source/common/uresdata.h
index 4e28ddc..5164740 100644
--- a/icu4c/source/common/uresdata.h
+++ b/icu4c/source/common/uresdata.h
@@ -69,14 +69,16 @@
 #define RES_GET_OFFSET(res) ((res)&0x0fffffff)
 #define RES_GET_POINTER(pRoot, res) ((pRoot)+RES_GET_OFFSET(res))
 
-/* get signed and unsigned integer values directly from the Resource handle */
+/* get signed and unsigned integer values directly from the Resource handle
+ * NOTE: For proper logging, please use the res_getInt() constexpr
+ */
 #if U_SIGNED_RIGHT_SHIFT_IS_ARITHMETIC
-#   define RES_GET_INT(res) (((int32_t)((res)<<4L))>>4L)
+#   define RES_GET_INT_NO_TRACE(res) (((int32_t)((res)<<4L))>>4L)
 #else
-#   define RES_GET_INT(res) (int32_t)(((res)&0x08000000) ? (res)|0xf0000000 : (res)&0x07ffffff)
+#   define RES_GET_INT_NO_TRACE(res) (int32_t)(((res)&0x08000000) ? (res)|0xf0000000 : (res)&0x07ffffff)
 #endif
 
-#define RES_GET_UINT(res) ((res)&0x0fffffff)
+#define RES_GET_UINT_NO_TRACE(res) ((res)&0x0fffffff)
 
 #define URES_IS_ARRAY(type) ((int32_t)(type)==URES_ARRAY || (int32_t)(type)==URES_ARRAY16)
 #define URES_IS_TABLE(type) ((int32_t)(type)==URES_TABLE || (int32_t)(type)==URES_TABLE16 || (int32_t)(type)==URES_TABLE32)
@@ -423,23 +425,27 @@
 U_INTERNAL UResType U_EXPORT2
 res_getPublicType(Resource res);
 
+///////////////////////////////////////////////////////////////////////////
+// To enable tracing, use the inline versions of the res_get* functions. //
+///////////////////////////////////////////////////////////////////////////
+
 /*
  * Return a pointer to a zero-terminated, const UChar* string
  * and set its length in *pLength.
  * Returns NULL if not found.
  */
 U_INTERNAL const UChar * U_EXPORT2
-res_getString(const ResourceData *pResData, Resource res, int32_t *pLength);
+res_getStringNoTrace(const ResourceData *pResData, Resource res, int32_t *pLength);
+
+U_INTERNAL const uint8_t * U_EXPORT2
+res_getBinaryNoTrace(const ResourceData *pResData, Resource res, int32_t *pLength);
+
+U_INTERNAL const int32_t * U_EXPORT2
+res_getIntVectorNoTrace(const ResourceData *pResData, Resource res, int32_t *pLength);
 
 U_INTERNAL const UChar * U_EXPORT2
 res_getAlias(const ResourceData *pResData, Resource res, int32_t *pLength);
 
-U_INTERNAL const uint8_t * U_EXPORT2
-res_getBinary(const ResourceData *pResData, Resource res, int32_t *pLength);
-
-U_INTERNAL const int32_t * U_EXPORT2
-res_getIntVector(const ResourceData *pResData, Resource res, int32_t *pLength);
-
 U_INTERNAL Resource U_EXPORT2
 res_getResource(const ResourceData *pResData, const char *key);
 
@@ -470,16 +476,54 @@
 #ifdef __cplusplus
 
 #include "resource.h"
+#include "restrace.h"
 
 U_NAMESPACE_BEGIN
 
+inline const UChar* res_getString(const ResourceTracer& traceInfo,
+        const ResourceData *pResData, Resource res, int32_t *pLength) {
+    traceInfo.trace("string");
+    return res_getStringNoTrace(pResData, res, pLength);
+}
+
+inline const uint8_t* res_getBinary(const ResourceTracer& traceInfo,
+        const ResourceData *pResData, Resource res, int32_t *pLength) {
+    traceInfo.trace("binary");
+    return res_getBinaryNoTrace(pResData, res, pLength);
+}
+
+inline const int32_t* res_getIntVector(const ResourceTracer& traceInfo,
+        const ResourceData *pResData, Resource res, int32_t *pLength) {
+    traceInfo.trace("intvector");
+    return res_getIntVectorNoTrace(pResData, res, pLength);
+}
+
+inline int32_t res_getInt(const ResourceTracer& traceInfo, Resource res) {
+    traceInfo.trace("int");
+    return RES_GET_INT_NO_TRACE(res);
+}
+
+inline uint32_t res_getUInt(const ResourceTracer& traceInfo, Resource res) {
+    traceInfo.trace("uint");
+    return RES_GET_UINT_NO_TRACE(res);
+}
+
 class ResourceDataValue : public ResourceValue {
 public:
-    ResourceDataValue() : pResData(NULL), res(static_cast<Resource>(URES_NONE)) {}
+    ResourceDataValue() :
+        pResData(NULL),
+        res(static_cast<Resource>(URES_NONE)),
+        fTraceInfo() {}
     virtual ~ResourceDataValue();
 
-    void setData(const ResourceData *data) { pResData = data; }
-    void setResource(Resource r) { res = r; }
+    void setData(const ResourceData *data) {
+        pResData = data;
+    }
+
+    void setResource(Resource r, ResourceTracer&& traceInfo) {
+        res = r;
+        fTraceInfo = traceInfo;
+    }
 
     virtual UResType getType() const;
     virtual const UChar *getString(int32_t &length, UErrorCode &errorCode) const;
@@ -501,6 +545,7 @@
 
 private:
     Resource res;
+    ResourceTracer fTraceInfo;
 };
 
 U_NAMESPACE_END
diff --git a/icu4c/source/common/utrace.cpp b/icu4c/source/common/utrace.cpp
index 2ac3d77..eced03b 100644
--- a/icu4c/source/common/utrace.cpp
+++ b/icu4c/source/common/utrace.cpp
@@ -476,6 +476,15 @@
     NULL
 };
 
+
+static const char* const
+trResDataNames[] = {
+    "ResourceTracer::trace",
+    "FileTracer::traceOpenDataFile",
+    "FileTracer::traceOpenResFile",
+    NULL
+};
+
                 
 U_CAPI const char * U_EXPORT2
 utrace_functionName(int32_t fnNumber) {
@@ -485,6 +494,8 @@
         return trConvNames[fnNumber - UTRACE_CONVERSION_START];
     } else if(UTRACE_COLLATION_START <= fnNumber && fnNumber < UTRACE_COLLATION_LIMIT){
         return trCollNames[fnNumber - UTRACE_COLLATION_START];
+    } else if(UTRACE_RES_DATA_START <= fnNumber && fnNumber < UTRACE_RES_DATA_LIMIT){
+        return trResDataNames[fnNumber - UTRACE_RES_DATA_START];
     } else {
         return "[BOGUS Trace Function Number]";
     }
diff --git a/icu4c/source/test/depstest/dependencies.txt b/icu4c/source/test/depstest/dependencies.txt
index 70b5211..2d04362 100644
--- a/icu4c/source/test/depstest/dependencies.txt
+++ b/icu4c/source/test/depstest/dependencies.txt
@@ -646,11 +646,12 @@
     resourcebundle
 
 group: udata
-    udata.o ucmndata.o udatamem.o
+    udata.o ucmndata.o udatamem.o restrace.o
     umapfile.o
   deps
     uhash platform stubdata
     file_io mmap_functions
+    icu_utility
 
 group: unifiedcache
     unifiedcache.o
diff --git a/icu4c/source/test/intltest/intltest.cpp b/icu4c/source/test/intltest/intltest.cpp
index 3d6793e..c73c700 100644
--- a/icu4c/source/test/intltest/intltest.cpp
+++ b/icu4c/source/test/intltest/intltest.cpp
@@ -2105,6 +2105,42 @@
 }
 #endif
 
+std::string vectorToString(const std::vector<std::string>& strings) {
+    std::string result = "{";
+    bool first = true;
+    for (auto element : strings) {
+        if (first) {
+            first = false;
+        } else {
+            result += ", ";
+        }
+        result += "\"";
+        result += element;
+        result += "\"";
+    }
+    result += "}";
+    return result;
+}
+
+UBool IntlTest::assertEquals(const char* message,
+                             const std::vector<std::string>& expected,
+                             const std::vector<std::string>& actual) {
+    if (expected != actual) {
+        std::string expectedAsString = vectorToString(expected);
+        std::string actualAsString = vectorToString(actual);
+        errln((UnicodeString)"FAIL: " + message +
+            "; got " + actualAsString.c_str() +
+            "; expected " + expectedAsString.c_str());
+        return FALSE;
+    }
+#ifdef VERBOSE_ASSERTIONS
+    else {
+        logln((UnicodeString)"Ok: " + message + "; got " + vectorToString(actual).c_str());
+    }
+#endif
+    return TRUE;
+}
+
 static char ASSERT_BUF[256];
 
 static const char* extractToAssertBuf(const UnicodeString& message) {
@@ -2169,6 +2205,11 @@
                              const UnicodeSet& actual) {
     return assertEquals(extractToAssertBuf(message), expected, actual);
 }
+UBool IntlTest::assertEquals(const UnicodeString& message,
+                             const std::vector<std::string>& expected,
+                             const std::vector<std::string>& actual) {
+    return assertEquals(extractToAssertBuf(message), expected, actual);
+}
 
 #if !UCONFIG_NO_FORMATTING
 UBool IntlTest::assertEquals(const UnicodeString& message,
diff --git a/icu4c/source/test/intltest/intltest.h b/icu4c/source/test/intltest/intltest.h
index 37227ba..281c2ab 100644
--- a/icu4c/source/test/intltest/intltest.h
+++ b/icu4c/source/test/intltest/intltest.h
@@ -18,6 +18,9 @@
 #include "unicode/testlog.h"
 #include "unicode/uniset.h"
 
+#include <vector>
+#include <string>
+
 U_NAMESPACE_USE
 
 #if U_PLATFORM == U_PF_OS390
@@ -297,6 +300,8 @@
     UBool assertEquals(const char* message, double expected, double actual);
     UBool assertEquals(const char* message, UErrorCode expected, UErrorCode actual);
     UBool assertEquals(const char* message, const UnicodeSet& expected, const UnicodeSet& actual);
+    UBool assertEquals(const char* message,
+        const std::vector<std::string>& expected, const std::vector<std::string>& actual);
 #if !UCONFIG_NO_FORMATTING
     UBool assertEquals(const char* message, const Formattable& expected,
                        const Formattable& actual, UBool possibleDataError=FALSE);
@@ -315,6 +320,8 @@
     UBool assertEquals(const UnicodeString& message, double expected, double actual);
     UBool assertEquals(const UnicodeString& message, UErrorCode expected, UErrorCode actual);
     UBool assertEquals(const UnicodeString& message, const UnicodeSet& expected, const UnicodeSet& actual);
+    UBool assertEquals(const UnicodeString& message,
+        const std::vector<std::string>& expected, const std::vector<std::string>& actual);
 
     virtual void runIndexedTest( int32_t index, UBool exec, const char* &name, char* par = NULL ); // overide !
 
diff --git a/icu4c/source/test/intltest/restsnew.cpp b/icu4c/source/test/intltest/restsnew.cpp
index 1c19fc8..27b5957 100644
--- a/icu4c/source/test/intltest/restsnew.cpp
+++ b/icu4c/source/test/intltest/restsnew.cpp
@@ -11,12 +11,42 @@
 #include "cstring.h"
 #include "unicode/unistr.h"
 #include "unicode/resbund.h"
+#include "unicode/brkiter.h"
+#include "unicode/utrace.h"
+#include "unicode/ucurr.h"
 #include "restsnew.h"
 
 #include <stdlib.h>
 #include <time.h>
 #include <string.h>
 #include <limits.h>
+#include <vector>
+#include <string>
+
+//***************************************************************************************
+
+void NewResourceBundleTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
+{
+    if (exec) logln("TestSuite ResourceBundleTest: ");
+    TESTCASE_AUTO_BEGIN;
+
+#if !UCONFIG_NO_FILE_IO && !UCONFIG_NO_LEGACY_CONVERSION
+    TESTCASE_AUTO(TestResourceBundles);
+    TESTCASE_AUTO(TestConstruction);
+    TESTCASE_AUTO(TestIteration);
+    TESTCASE_AUTO(TestOtherAPI);
+    TESTCASE_AUTO(TestNewTypes);
+#endif
+
+    TESTCASE_AUTO(TestGetByFallback);
+    TESTCASE_AUTO(TestFilter);
+
+#if U_ENABLE_TRACING
+    TESTCASE_AUTO(TestTrace);
+#endif
+
+    TESTCASE_AUTO_END;
+}
 
 //***************************************************************************************
 
@@ -180,27 +210,6 @@
     }
 }
 
-void NewResourceBundleTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
-{
-    if (exec) logln("TestSuite ResourceBundleTest: ");
-    switch (index) {
-#if !UCONFIG_NO_FILE_IO && !UCONFIG_NO_LEGACY_CONVERSION
-    case 0: name = "TestResourceBundles"; if (exec) TestResourceBundles(); break;
-    case 1: name = "TestConstruction"; if (exec) TestConstruction(); break;
-    case 2: name = "TestIteration"; if (exec) TestIteration(); break;
-    case 3: name = "TestOtherAPI";  if(exec) TestOtherAPI(); break;
-    case 4: name = "TestNewTypes";  if(exec) TestNewTypes(); break;
-#else
-    case 0: case 1: case 2: case 3: case 4: name = "skip"; break;
-#endif
-
-    case 5: name = "TestGetByFallback";  if(exec) TestGetByFallback(); break;
-    case 6: name = "TestFilter";  if(exec) TestFilter(); break;
-
-        default: name = ""; break; //needed to end loop
-    }
-}
-
 //***************************************************************************************
 
 void
@@ -1343,5 +1352,86 @@
     }
 }
 
+#if U_ENABLE_TRACING
+
+static std::vector<std::string> gResourcePathsTraced;
+static std::vector<std::string> gDataFilesTraced;
+static std::vector<std::string> gResFilesTraced;
+
+static void U_CALLCONV traceData(
+        const void*,
+        int32_t fnNumber,
+        int32_t,
+        const char *,
+        va_list args) {
+
+    if (fnNumber == UTRACE_UDATA_RESOURCE) {
+        va_arg(args, const char*); // type
+        va_arg(args, const char*); // file
+        const char* resourcePath = va_arg(args, const char*);
+        gResourcePathsTraced.push_back(resourcePath);
+    } else if (fnNumber == UTRACE_UDATA_DATA_FILE) {
+        const char* filePath = va_arg(args, const char*);
+        gDataFilesTraced.push_back(filePath);
+    } else if (fnNumber == UTRACE_UDATA_RES_FILE) {
+        const char* filePath = va_arg(args, const char*);
+        gResFilesTraced.push_back(filePath);
+    }
+}
+
+void NewResourceBundleTest::TestTrace() {
+    IcuTestErrorCode status(*this, "TestTrace");
+
+    const void* context;
+    utrace_setFunctions(context, nullptr, nullptr, traceData);
+    utrace_setLevel(UTRACE_VERBOSE);
+
+    {
+        LocalPointer<BreakIterator> brkitr(BreakIterator::createWordInstance("zh-CN", status));
+
+        assertEquals("Should touch expected resource paths",
+            { "/boundaries/word" },
+            gResourcePathsTraced);
+        assertEquals("Should touch expected data files",
+            { U_ICUDATA_NAME "-brkitr/word.brk" },
+            gDataFilesTraced);
+        // NOTE: The following passes only when this test is run in isolation.
+        // If run in "make check", these files were already open.
+        // assertEquals("Should touch expected resource files",
+        //     {
+        //         U_ICUDATA_NAME "-brkitr/zh_CN.res",
+        //         U_ICUDATA_NAME "-brkitr/zh.res",
+        //         U_ICUDATA_NAME "-brkitr/root.res"
+        //     },
+        //     gResFilesTraced);
+        gResourcePathsTraced.clear();
+        gDataFilesTraced.clear();
+        gResFilesTraced.clear();
+    }
+
+    {
+        ucurr_getDefaultFractionDigits(u"USD", status);
+
+        assertEquals("Should touch expected resource paths",
+            { "/CurrencyMeta/DEFAULT" },
+            gResourcePathsTraced);
+        assertEquals("Should touch expected data files",
+            { },
+            gDataFilesTraced);
+        // NOTE: The following passes only when this test is run in isolation.
+        // If run in "make check", these files were already open.
+        // assertEquals("Should touch expected resource files",
+        //     { U_ICUDATA_NAME "-curr/supplementalData.res" },
+        //     gResFilesTraced);
+        gResourcePathsTraced.clear();
+        gDataFilesTraced.clear();
+        gResFilesTraced.clear();
+    }
+
+    utrace_setFunctions(context, nullptr, nullptr, nullptr);
+}
+
+#endif
+
 //eof
 
diff --git a/icu4c/source/test/intltest/restsnew.h b/icu4c/source/test/intltest/restsnew.h
index e951587..9ae3bf0 100644
--- a/icu4c/source/test/intltest/restsnew.h
+++ b/icu4c/source/test/intltest/restsnew.h
@@ -40,6 +40,10 @@
 
     void TestFilter(void);
 
+#if U_ENABLE_TRACING
+    void TestTrace(void);
+#endif
+
 private:
     /**
      * The assignment operator has no real implementation.
diff --git a/icu4c/source/tools/toolutil/pkgitems.cpp b/icu4c/source/tools/toolutil/pkgitems.cpp
index cb23b45..7b86c55 100644
--- a/icu4c/source/tools/toolutil/pkgitems.cpp
+++ b/icu4c/source/tools/toolutil/pkgitems.cpp
@@ -305,7 +305,8 @@
                 break;
             }
             int32_t length;
-            const UChar *alias=res_getString(pResData, res, &length);
+            // No tracing: build tool
+            const UChar *alias=res_getStringNoTrace(pResData, res, &length);
             checkAlias(itemName, res, alias, length, useResSuffix, check, context, pErrorCode);
         }
         break;