Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
将日志记录到文件是语音 SDK 的可选功能。 在开发期间,日志记录可以提供来自语音 SDK 核心组件的附加信息和诊断数据。 语音 SDK 的本机库中的静态类负责处理日志记录。 同一进程中的所有实例都将日志条目写入相同日志文件。
使用日志记录 API
启用日志记录的建议方法是使用语音 SDK 版本 1.43.0 及更高版本中提供的静态记录器类。 日志记录 API 提供三种类型的记录器:
- 文件记录器:将日志消息直接写入文件。 这是最简单的日志记录解决方案,适用于诊断大多数设备问题。
- 内存记录器:将日志消息存储在内存中的固定 2 MB 环形缓冲区中。 可以随时将缓冲区内容转储到文件或流。 这适用于诊断在短时间内发生的问题。
- 事件日志器:将日志消息发送到提供的事件处理程序。 当需要将语音 SDK 日志与现有日志记录收集系统集成时,这很合适。
这些记录器是覆盖整个进程的构造。 如果有多个语音识别器对象并行运行,则存在一个共享日志,其中包含来自所有识别器的交错日志行。 可以在同一进程中同时使用文件记录器、内存记录器和事件日志器。
使用语音 SDK 版本 1.43.0,日志记录机制通过更多类型的记录器进行扩展:File loggerMemory logger和Event logger。
File logger是最简单的日志记录解决方案,适用于在运行语音 SDK 时诊断大多数设备上的问题。Memory logger是一种日志记录解决方案,用于将日志消息存储在内存中。 它适用于诊断在短时间内发生的问题。 例如,如果您正在运行一个语音识别器,那么在收到因某些错误而导致识别取消的事件后,您可能希望导出内存日志。 内存缓冲区的大小固定在 2MB 处,无法更改。 这是一个“环形”缓冲区,即写入的新日志字符串将替换缓冲区中最早的字符串。Event logger是一种日志记录解决方案,用于将日志消息发送到开发人员提供的事件处理程序。 某些新的日志字符串一旦可用并需要进一步处理时,它适用于诊断问题。 例如,将语音 SDK 日志与现有日志记录收集系统集成。
文件记录器、内存记录器和事件记录器都有筛选机制,可以通过仅记录特定的字符串消息来实现。 此外,这些记录器是进程范围的构造。 这意味着,如果(例如)有多个语音识别器对象并行运行,则有一个日志文件包含来自所有识别器的交错日志行。 无法为每个识别器获取单独的文件记录器。 同样,有一个内存缓冲区包含来自所有识别器的交错日志,并且只能将一个事件处理程序注册为回调函数,以接收来自所有识别器的交错日志。 无法为每个识别器获取单独的内存记录器,并且无法为每个识别器注册事件处理程序。 但是, File logger, memory logger and event logger 可以在同一进程中或同一识别器中共存。
示例
using Microsoft.CognitiveServices.Speech;
using Microsoft.CognitiveServices.Speech.Diagnostics.Logging;
class Program
{
public static void FileLoggerWithoutFilters()
{
FileLogger.Start("LogfilePathAndName");
// Other Speech SDK calls
FileLogger.Stop();
}
public static void FileLoggerWithFilters()
{
string[] filters = { "YourFirstString", "YourSecondString" };
FileLogger.SetFilters(filters);
FileLogger.Start("LogfilePathAndName");
// Other Speech SDK calls
FileLogger.Stop();
FileLogger.SetFilters();
}
public static void MemoryLoggerWithoutFilters()
{
MemoryLogger.Start();
// Other Speech SDK calls
// At any time (whether logging is stopped) you can dump the traces in memory to a file
MemoryLogger.Dump("LogfilePathAndName");
// Or dump to any object that is derived from System.IO.TextWriter. For example, System.Console.Out
MemoryLogger.Dump(System.Console.Out);
// Or dump to a vector of strings
List<string> messages = MemoryLogger.Dump().ToList<string>();
MemoryLogger.Stop();
}
// These variables and method are used by the EvenLogger sample below.
private static readonly object lockObject = new object();
private static List<string> eventMessages = new List<string>();
private static void OnMessageEvent(object sender, string message)
{
lock (lockObject)
{
// Store the message for later processing. Better not processing it in the event thread
eventMessages.Add(message);
}
}
public static void EventLoggerWithoutFilters()
{
// Subscribe an event that will get invoked by Speech SDK on every new log message
EventLogger.OnMessage += OnMessageEvent;
// Other Speech SDK calls
// Unsubscribe to stop getting events
EventLogger.OnMessage -= OnMessageEvent;
}
}
使用语音 SDK 版本 1.43.0,日志记录机制通过更多类型的记录器进行扩展:File loggerMemory logger和Event logger。
File logger是最简单的日志记录解决方案,适用于在运行语音 SDK 时诊断大多数设备上的问题。Memory logger是一种日志记录解决方案,用于将日志消息存储在内存中。 它适用于诊断在短时间内发生的问题。 例如,如果您正在运行一个语音识别器,那么在收到因某些错误而导致识别取消的事件后,您可能希望导出内存日志。 内存缓冲区的大小固定在 2MB 处,无法更改。 这是一个“环形”缓冲区,即写入的新日志字符串将替换缓冲区中最早的字符串。Event logger是一种日志记录解决方案,用于将日志消息发送到开发人员提供的事件处理程序。 某些新的日志字符串一旦可用并需要进一步处理时,它适用于诊断问题。 例如,将语音 SDK 日志与现有日志记录收集系统集成。
文件记录器、内存记录器和事件记录器都有筛选机制,可以通过仅记录特定的字符串消息来实现。 此外,这些记录器是进程范围的构造。 这意味着,如果(例如)有多个语音识别器对象并行运行,则有一个日志文件包含来自所有识别器的交错日志行。 无法为每个识别器获取单独的文件记录器。 同样,有一个内存缓冲区包含来自所有识别器的交错日志,并且只能将一个事件处理程序注册为回调函数,以接收来自所有识别器的交错日志。 无法为每个识别器获取单独的内存记录器,并且无法为每个识别器注册事件处理程序。 但是, File logger, memory logger and event logger 可以在同一进程中或同一识别器中共存。
示例
using namespace Microsoft::CognitiveServices::Speech;
using namespace Microsoft::CognitiveServices::Speech::Diagnostics::Logging;
void FileLoggerWithoutFilters()
{
FileLogger::Start("LogfilePathAndName");
// Other Speech SDK calls
FileLogger::Stop();
}
void FileLoggerWithFilters()
{
std::initializer_list<std::string> filters = { "YourFirstString", "YourSecondString" };
FileLogger::SetFilters(filters);
FileLogger::Start("LogfilePathAndName");
// Other Speech SDK calls
FileLogger::Stop();
FileLogger::SetFilters();
}
void MemoryLoggerWithoutFilters()
{
MemoryLogger::Start();
// Other Speech SDK calls
// At any time (whether logging is stopped) you can dump the traces in memory to a file
MemoryLogger::Dump("LogfilePathAndName");
// Or dump to any stream object that is derived from std::ostream. For example, std::cout
MemoryLogger::Dump(std::cout);
// Or dump to a vector of strings
std::vector<std::string> messages = MemoryLogger::Dump();
MemoryLogger::Stop();
}
void EventLoggerWithoutFilters()
{
std::mutex mtx;
std::vector<std::string> messages;
// Register a callback that will get invoked by Speech SDK on every new log message
EventLogger::SetCallback([&messages, &mtx](std::string message) {
// Store the message for later processing. Better not processing it in the event thread
std::unique_lock<std::mutex> lock(mtx);
messages.push_back(message);
});
// Other Speech SDK calls
// Stop logging by setting an empty callback
EventLogger::SetCallback();
}
使用语音 SDK 版本 1.43.0,日志记录机制通过更多类型的记录器进行扩展:File loggerMemory logger和Event logger。
File logger是最简单的日志记录解决方案,适用于在运行语音 SDK 时诊断大多数设备上的问题。Memory logger是一种日志记录解决方案,用于将日志消息存储在内存中。 它适用于诊断在短时间内发生的问题。 例如,如果您正在运行一个语音识别器,那么在收到因某些错误而导致识别取消的事件后,您可能希望导出内存日志。 内存缓冲区的大小固定在 2MB 处,无法更改。 这是一个“环形”缓冲区,即写入的新日志字符串将替换缓冲区中最早的字符串。Event logger是一种日志记录解决方案,用于将日志消息发送到开发人员提供的事件处理程序。 某些新的日志字符串一旦可用并需要进一步处理时,它适用于诊断问题。 例如,将语音 SDK 日志与现有日志记录收集系统集成。
文件记录器、内存记录器和事件记录器都有筛选机制,可以通过仅记录特定的字符串消息来实现。 此外,这些记录器是进程范围的构造。 这意味着,如果(例如)有多个语音识别器对象并行运行,则有一个日志文件包含来自所有识别器的交错日志行。 无法为每个识别器获取单独的文件记录器。 同样,有一个内存缓冲区包含来自所有识别器的交错日志,并且只能将一个事件处理程序注册为回调函数,以接收来自所有识别器的交错日志。 无法为每个识别器获取单独的内存记录器,并且无法为每个识别器注册事件处理程序。 但是, File logger, memory logger and event logger 可以在同一进程中或同一识别器中共存。
示例
import com.microsoft.cognitiveservices.speech.*;
import com.microsoft.cognitiveservices.speech.diagnostics.logging.EventLogger;
import com.microsoft.cognitiveservices.speech.diagnostics.logging.FileLogger;
import com.microsoft.cognitiveservices.speech.diagnostics.logging.MemoryLogger;
public class SpeechLoggingSamples {
public static void fileLoggerWithoutFilters()
{
FileLogger.start("LogfilePathAndName");
// Other Speech SDK calls
FileLogger.stop();
}
public static void FileLoggerWithFilters()
{
String[] filters = { "YourFirstString", "YourSecondString" };
FileLogger.setFilters(filters);
FileLogger.start("LogfilePathAndName");
// Other Speech SDK calls
FileLogger.stop();
FileLogger.setFilters();
}
public static void memoryLoggerWithoutFilters()
{
MemoryLogger.start();
// Other Speech SDK calls
// At any time (whether logging is stopped) you can dump the traces in memory to a file
MemoryLogger.dump("LogfilePathAndName");
// Or dump to any object that is derived from java.io.Writer. For example, System.out
MemoryLogger.dump(System.out);
// Or dump to a list of strings
List<String> messages = MemoryLogger.dump();
MemoryLogger.stop();
}
public static void eventLoggerWithoutFilters()
{
final Object lockObject = new Object();
List<String> messages = new ArrayList<>();
// Register a callback that will get invoked by Speech SDK on every new log message
EventLogger.setCallback((message) -> {
// Store the message for later processing. Better not processing it in the event thread
synchronized (lockObject) {
messages.add(message);
}
});
// Other Speech SDK calls
// Stop logging by setting an empty callback
EventLogger.setCallback();
}
}
使用语音 SDK 版本 1.43.0,日志记录机制通过更多类型的记录器进行扩展:File loggerMemory logger和Event logger。
File logger是最简单的日志记录解决方案,适用于在运行语音 SDK 时诊断大多数设备上的问题。Memory logger是一种日志记录解决方案,用于将日志消息存储在内存中。 它适用于诊断在短时间内发生的问题。 例如,如果您正在运行一个语音识别器,那么在收到因某些错误而导致识别取消的事件后,您可能希望导出内存日志。 内存缓冲区的大小固定在 2MB 处,无法更改。 这是一个“环形”缓冲区,即写入的新日志字符串将替换缓冲区中最早的字符串。Event logger是一种日志记录解决方案,用于将日志消息发送到开发人员提供的事件处理程序。 某些新的日志字符串一旦可用并需要进一步处理时,它适用于诊断问题。 例如,将语音 SDK 日志与现有日志记录收集系统集成。
文件记录器、内存记录器和事件记录器都有筛选机制,可以通过仅记录特定的字符串消息来实现。 此外,这些记录器是进程范围的构造。 这意味着,如果(例如)有多个语音识别器对象并行运行,则有一个日志文件包含来自所有识别器的交错日志行。 无法为每个识别器获取单独的文件记录器。 同样,有一个内存缓冲区包含来自所有识别器的交错日志,并且只能将一个事件处理程序注册为回调函数,以接收来自所有识别器的交错日志。 无法为每个识别器获取单独的内存记录器,并且无法为每个识别器注册事件处理程序。 但是, File logger, memory logger and event logger 可以在同一进程中或同一识别器中共存。
示例
- (void)fileLoggerWithoutFilters {
NSString *logFileName = @"speech_sdk.log";
NSString *logFile = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]
stringByAppendingPathComponent:logFileName];
[SPXFileLogger start:logFile];
// Other Speech SDK calls
[SPXFileLogger stop];
}
- (void)fileLoggerWithFilters {
NSString *logFileName = @"speech_sdk.log";
NSString *logFile = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]
stringByAppendingPathComponent:logFileName];
NSArray *filters = @[@"YourFirstString", @"YourSecondString"];
[SPXFileLogger setFilters:filters];
[SPXFileLogger start:logFile];
// Other Speech SDK calls
[SPXFileLogger stop];
[SPXFileLogger setFilters:nil];
}
- (void)memoryLoggerWithoutFilters {
NSString *logFileName = @"speech_sdk.log";
NSString *logFile = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]
stringByAppendingPathComponent:logFileName];
[SPXMemoryLogger start];
// Other Speech SDK calls
// At any time (whether logging is stopped) you can dump the traces in memory to a file
[SPXMemoryLogger dumpToFile:logFile];
[SPXMemoryLogger stop];
}
- (void)eventLoggingWithoutFilters {
__block NSMutableArray *eventMsgs = [NSMutableArray array];
// Register a callback that will get invoked by Speech SDK on every new log message
[SPXEventLogger setCallback:^(NSString *message) {
@synchronized(self) {
[eventMsgs addObject:message];
}
}];
// Other Speech SDK calls
// Stop event logging
[SPXEventLogger setCallback:nil];
}
使用语音 SDK 版本 1.43.0,日志记录机制通过更多类型的记录器进行扩展:File loggerMemory logger和Event logger。
File logger是最简单的日志记录解决方案,适用于在运行语音 SDK 时诊断大多数设备上的问题。Memory logger是一种日志记录解决方案,用于将日志消息存储在内存中。 它适用于诊断在短时间内发生的问题。 例如,如果您正在运行一个语音识别器,那么在收到因某些错误而导致识别取消的事件后,您可能希望导出内存日志。 内存缓冲区的大小固定在 2MB 处,无法更改。 这是一个“环形”缓冲区,即写入的新日志字符串将替换缓冲区中最早的字符串。Event logger是一种日志记录解决方案,用于将日志消息发送到开发人员提供的事件处理程序。 某些新的日志字符串一旦可用并需要进一步处理时,它适用于诊断问题。 例如,将语音 SDK 日志与现有日志记录收集系统集成。
文件记录器、内存记录器和事件记录器都有筛选机制,可以通过仅记录特定的字符串消息来实现。 此外,这些记录器是进程范围的构造。 这意味着,如果(例如)有多个语音识别器对象并行运行,则有一个日志文件包含来自所有识别器的交错日志行。 无法为每个识别器获取单独的文件记录器。 同样,有一个内存缓冲区包含来自所有识别器的交错日志,并且只能将一个事件处理程序注册为回调函数,以接收来自所有识别器的交错日志。 无法为每个识别器获取单独的内存记录器,并且无法为每个识别器注册事件处理程序。 但是, File logger, memory logger and event logger 可以在同一进程中或同一识别器中共存。
示例
import azure.cognitiveservices.speech as speechsdk
import azure.cognitiveservices.speech.diagnostics.logging as speechsdk_logging
def file_logger_without_filters():
speechsdk_logging.FileLogger.start("LogfilePathAndName")
# Other Speech SDK calls
speechsdk_logging.FileLogger.stop()
def file_logger_with_filters():
filters = { "YourFirstString", "YourSecondString" }
speechsdk_logging.FileLogger.set_filters(filters)
speechsdk_logging.FileLogger.start("LogfilePathAndName")
# Other Speech SDK calls
speechsdk_logging.FileLogger.stop()
speechsdk_logging.FileLogger.set_filters()
def memory_logger_without_filter():
speechsdk_logging.MemoryLogger.start()
#
# Other Speech SDK calls
#
# At any time (whether logging is stopped) you can dump the traces in memory to a file
speechsdk_logging.MemoryLogger.dump("LogfilePathAndName")
# Or dump to any object that is derived from IOBase. For example, sys.stdout
speechsdk_logging.MemoryLogger.dump_to_stream(sys.stdout)
# Or dump to a list of strings
messages = speechsdk_logging.MemoryLogger.dump_to_list()
speechsdk_logging.MemoryLogger.stop()
def event_logger_without_filter():
messages = []
lock = threading.Lock()
# Register a callback that will get invoked by Speech SDK on every new log message
def on_log(msg):
with lock:
# Store the message for later processing. Better not processing it in the event thread
messages.append(msg)
speechsdk_logging.EventLogger.set_callback(on_log)
#
# Other Speech SDK calls
#
# Stop logging by setting an empty callback
speechsdk_logging.EventLogger.set_callback()
JavaScript
对于 JavaScript,日志记录通过 SDK 调试工具启用:
sdk.Diagnostics.SetLoggingLevel(sdk.LogLevel.Debug);
sdk.Diagnostics.SetLogOutputPath("LogfilePathAndName");
按平台列出的日志文件位置
使用 FileLogger.Start() 或 MemoryLogger.Dump() 时,需要提供文件路径。 路径要求因平台而异。
对于 Windows 或 Linux,日志文件可以位于用户具有写入权限的任何路径中。 默认情况下,对其他操作系统中的文件系统位置的写入权限可能会受到限制。
Universal Windows Platform (UWP)
UWP 应用程序需要在某个应用程序数据位置(本地、漫游或临时)中放置日志文件。 可在本地应用程序文件夹中创建日志文件:
StorageFolder storageFolder = ApplicationData.Current.LocalFolder;
StorageFile logFile = await storageFolder.CreateFileAsync("logfile.txt", CreationCollisionOption.ReplaceExisting);
FileLogger.Start(logFile.Path);
在 Unity UWP 应用程序中,可以使用应用程序持久数据路径文件夹创建日志文件,如下所示:
#if ENABLE_WINMD_SUPPORT
string logFile = Application.persistentDataPath + "/logFile.txt";
FileLogger.Start(logFile);
#endif
有关 UWP 应用程序中文件访问权限的详细信息,请参阅文件访问权限。
Android
可将日志文件保存到内部存储、外部存储或缓存目录。 在内部存储或缓存目录中创建的文件专用于应用程序。 最好是在外部存储中创建日志文件。
File dir = context.getExternalFilesDir(null);
File logFile = new File(dir, "logfile.txt");
FileLogger.start(logFile.getAbsolutePath());
该代码将日志文件保存到应用程序特定目录的根目录中的外部存储。 用户可以使用文件管理器访问该文件(通常位于 Android/data/ApplicationName/logfile.txt)。 卸载应用程序时,会删除该文件。
还需要请求清单文件中的 WRITE_EXTERNAL_STORAGE 权限:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="...">
...
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
...
</manifest>
在 Unity Android 应用程序中,可以使用应用程序持久数据路径文件夹创建日志文件,如下所示:
string logFile = Application.persistentDataPath + "/logFile.txt";
FileLogger.Start(logFile);
此外,需要在 Android 的 Unity Player 设置中将写入权限设置为“External (SDCard)”。 日志将写入可以使用 AndroidStudio 设备文件资源管理器等工具获取的目录中。 Android 设备之间的确切目录路径可能会有所不同。 位置通常是 sdcard/Android/data/your-app-packagename/files 目录。
有关 Android 应用程序的数据和文件存储的详细信息,请参阅 数据和文件存储概述。
iOS
只能访问应用程序沙盒中的目录。 可以在文档、库和临时目录中创建文件。 文档目录中的文件可供用户使用。
如果在 iOS 上使用 Objective-C,请使用以下代码片段在应用程序文档目录中创建日志文件:
NSString *filePath = [
[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]
stringByAppendingPathComponent:@"logfile.txt"];
[SPXFileLogger start:filePath];
若要访问已创建的文件,请将以下属性添加到 Info.plist 应用程序的属性列表中:
<key>UIFileSharingEnabled</key>
<true/>
<key>LSSupportsOpeningDocumentsInPlace</key>
<true/>
如果在 iOS 上使用 Swift,请使用以下代码片段启用日志:
let documentsDirectoryPathString = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first!
let documentsDirectoryPath = NSURL(string: documentsDirectoryPathString)!
let logFilePath = documentsDirectoryPath.appendingPathComponent("swift.log")
SPXFileLogger.start(logFilePath!.absoluteString)
有关 iOS 文件系统的详细信息,请参阅 文件系统编程指南。
旧方法:在配置对象上设置属性
还可以通过在语音配置对象上设置 Speech_LogFilename 属性来启用日志记录。 此方法的灵活性不如使用静态记录器类。
以 SpeechConfig 为例,假设你已创建名为 speechConfig 的实例:
speechConfig.SetProperty(PropertyId.Speech_LogFilename, "LogfilePathAndName");
speechConfig.setProperty(PropertyId.Speech_LogFilename, "LogfilePathAndName");
speechConfig->SetProperty(PropertyId::Speech_LogFilename, "LogfilePathAndName");
speech_config.set_property(speechsdk.PropertyId.Speech_LogFilename, "LogfilePathAndName")
[speechConfig setPropertyTo:@"LogfilePathAndName" byId:SPXSpeechLogFilename];
import ("github.com/Microsoft/cognitive-services-speech-sdk-go/common")
speechConfig.SetProperty(common.SpeechLogFilename, "LogfilePathAndName")
可以基于配置对象创建识别器。 这将为所有识别器启用日志记录。
注释
如果从配置对象创建一个 SpeechSynthesizer ,则不会启用日志记录。 不过,如果启用了日志记录,您还会从SpeechSynthesizer接收到诊断信息。
有关特定于平台的文件路径指南,请参阅 按平台列出的日志文件位置。 使用属性方法时,相同的路径要求适用。
用多个识别器进行日志记录
使用传统属性方法时,日志文件输出路径被指定为 SpeechRecognizer 或其他 SDK 对象中的配置属性。 但是,SDK 日志记录是单一进程范围的设施,没有单个实例的概念。 可以将其视为 SpeechRecognizer 构造函数(或类似构造函数),使用相应 SpeechConfig 中提供的属性数据隐式调用静态和内部“配置全局日志记录”例程。
举例来说,这意味着不能将六个并行识别器配置为同时输出到六个单独的文件。 相反,创建的最新识别器将配置全局日志记录实例,以输出到其配置属性中指定的文件,并将所有 SDK 日志记录发送到该文件。
这也意味着已配置日志记录的对象的生存期与日志记录的持续时间无关。 日志记录不会因为 SDK 对象的发布而停止,只要没有提供新的日志记录配置,日志记录就会继续。 一旦启动,可以通过在创建新对象时将日志文件路径设置为空字符串来停止整个进程的日志记录。
为了减少在为多个实例配置日志记录时可能出现的混乱,将日志记录的控制从执行实际工作的对象中抽象出来可能很有用。 一组辅助例程示例:
void EnableSpeechSdkLogging(const char* relativePath)
{
auto configForLogging = SpeechConfig::FromSubscription("unused_key", "unused_region");
configForLogging->SetProperty(PropertyId::Speech_LogFilename, relativePath);
auto emptyAudioConfig = AudioConfig::FromStreamInput(AudioInputStream::CreatePushStream());
auto temporaryRecognizer = SpeechRecognizer::FromConfig(configForLogging, emptyAudioConfig);
}
void DisableSpeechSdkLogging()
{
EnableSpeechSdkLogging("");
}