Tous les produits
Search
Centre de documentation

ApsaraVideo VOD:Système de journalisation

Dernière mise à jour :Sep 11, 2026

Le système de journalisation est un module fondamental d'AliPlayerKit. Il s'appuie sur un centre de journalisation unifié, LogHub, pour offrir des fonctionnalités essentielles telles que la sortie des journaux, le filtrage par niveau et un mécanisme d'observateur. Cela garantit la visibilité et la traçabilité des informations d'exécution du lecteur.

Concepts

Qu'est-ce que LogHub ?

LogHub constitue le point d'entrée unique pour toutes les sorties de journal dans AliPlayerKit. Conçu selon le modèle singleton, LogHub encapsule l'API de journalisation native d'iOS, NSLog, et ajoute les fonctionnalités principales suivantes :

Fonctionnalités

Description

Interrupteur de journalisation

Contrôle l'activation ou la désactivation de la sortie des journaux (interrupteur principal).

Interrupteur de console

Contrôle l'affichage des journaux dans la console Xcode.

Filtrage par niveau

Affiche uniquement les journaux dont le niveau est égal ou supérieur au niveau spécifié.

Mécanisme d'observateur

Permet aux observateurs externes de recevoir les sorties de journal pour un traitement personnalisé, comme l'écriture dans un fichier.

Qu'est-ce qu'un observateur de journal ?

Un observateur de journal (LogObserver) est un protocole de rappel utilisé pour recevoir les journaux depuis LogHub. En implémentant ce protocole, vous pouvez personnaliser le traitement des journaux. Par exemple :

  • Écrire les journaux dans un fichier afin que l'équipe de support technique puisse les utiliser pour le dépannage.

  • Télécharger les journaux vers un serveur distant pour activer la collecte à distance.

  • Afficher les journaux dans l'interface utilisateur pour créer un panneau de débogage.

Modèle de threads hybride

LogHub utilise un modèle de threads hybride :

Opération

Thread

Capture du nom du thread et de l'horodatage

Exécution synchrone dans le thread appelant

Sortie console (NSLog)

Exécution synchrone dans le thread appelant

Notification des observateurs

Distribution asynchrone vers une file d'attente série en arrière-plan

Remarque

Le rappel LogObserver.onLog: s'exécute dans une file d'attente série en arrière-plan. Vous devez basculer vers le thread principal pour mettre à jour l'interface utilisateur.

Fonctionnalités

Fonctionnalités principales

Fonctionnalités

Description

Journalisation multiniveau

Prend en charge cinq niveaux : Verbose, Debug, Info, Warn et Error.

Triple contrôle

Interrupteur global, filtrage par niveau et interrupteur de console pour un contrôle précis de la portée de sortie.

Mécanisme d'observateur

Vous permet d'enregistrer des observateurs personnalisés pour la persistance des journaux, la remontée à distance, etc.

Macros d'aide

Fournit les macros SLOGV/D/I/W/E qui capturent automatiquement l'emplacement du code source.

Panneau de journalisation

Affiche les journaux en temps réel dans la vue du lecteur à l'aide de LogPanelSlot (uniquement pour le débogage).

API de raccourci global

Configurez rapidement les niveaux de journalisation et la sortie console à l'aide des méthodes de classe AliPlayerKit.

Composants principaux

Composant

Type

Description

LogHub

Singleton

Centre de journalisation, point d'entrée unique pour la sortie des journaux.

LogLevel

Énumération

Définition du niveau de journalisation.

LogInfo

Classe de données

Modèle d'informations de journal qui encapsule toutes les informations d'une entrée de journal unique.

LogObserver

Protocole

Interface de l'observateur de journal.

LogPanelSlot

Emplacement (Slot)

Panneau de journalisation intégré au lecteur qui affiche les journaux clés en temps réel.

Utilisation

Utilisation de base : configuration rapide globale

Vous pouvez configurer rapidement le système de journalisation à l'aide des méthodes de classe recommandées AliPlayerKit :

// In AppDelegate, configure after setup
[AliPlayerKit setup];

// Set the log level
[AliPlayerKit setLogLevel:LogLevelVerbose];

// Enable or disable console logs
[AliPlayerKit enableConsoleLog:YES];

Méthode AliPlayerKit

Description

setLogLevel:

Définit le niveau de journalisation. Les journaux inférieurs à ce niveau sont ignorés. La valeur par défaut est LogLevelInfo.

logLevel

Récupère le niveau de journalisation actuel.

enableConsoleLog:

Active ou désactive la sortie console. Activé par défaut.

isConsoleLogEnabled

Vérifie si la journalisation console est activée.

setDebugModeEnabled:

Active ou désactive le mode débogage.

isDebugModeEnabled

Vérifie si le mode débogage est activé.

setLogPanelEnabled:

Active ou désactive l'emplacement du panneau de journalisation. Désactivé par défaut.

isLogPanelEnabled

Vérifie si le panneau de journalisation est activé.

Utilisation de base : sortie de journal

Utilisez les macros d'aide de la série SLOG pour générer des journaux à différents niveaux. Ces macros capturent automatiquement le nom du fichier source et le numéro de ligne :

#import <AliPlayerKit/LogMacros.h>

// Output logs at different levels (automatically captures __FILE_NAME__ and __LINE__)
SLOGV(@"viewDidLoad called");
SLOGD(@"Configure player: videoId=%@", videoId);
SLOGI(@"Start playing video: %@", videoTitle);
SLOGW(@"Buffering, current progress: %.1f%%", progress * 100);
SLOGE(@"Playback failed, error code: %ld", (long)errorCode);

Liste des macros d'aide :

Macro

Niveau

Description

SLOGV(fmt, ...)

Verbose

Niveau de journal le plus détaillé.

SLOGD(fmt, ...)

Debug

Informations de débogage.

SLOGI(fmt, ...)

Info

Informations générales.

SLOGW(fmt, ...)

Warn

Problèmes potentiels.

SLOGE(fmt, ...)

Error

Messages d'erreur.

Remarque

Les macros SLOG appellent la méthode LogHub logLevel:file:line:message:error:. Elles capturent automatiquement l'emplacement du code source à l'aide de __FILE_NAME__ et __LINE__, vous n'avez donc pas besoin de transmettre manuellement un tag.

Vous pouvez également appeler directement les méthodes d'instance de LogHub et spécifier manuellement un tag :

// Use a tag to identify the log source
[[LogHub sharedHub] i:@"PlayerVC" msg:@"Start playback"];
[[LogHub sharedHub] e:@"MediaPlayer" msg:@"Playback failed" error:error];

Utilisation de base : configuration des niveaux de journalisation

Configurez les propriétés de journalisation directement via LogHub :

LogHub *logHub = [LogHub sharedHub];

#ifdef DEBUG
    // Development environment: Verbose logs + console output
    logHub.logEnabled = YES;
    logHub.consoleLogEnabled = YES;
    logHub.logLevel = LogLevelVerbose;
#else
    // Production environment: Concise logs + console disabled
    logHub.logEnabled = YES;
    logHub.consoleLogEnabled = NO;
    logHub.logLevel = LogLevelInfo;
#endif

Mécanisme de triple contrôle :

Couche de contrôle

Propriété

Description

Interrupteur principal

logEnabled

Lorsqu'il est désactivé, toute la journalisation est silencieuse, y compris les notifications aux observateurs.

Filtrage par niveau

logLevel

Les journaux inférieurs à ce niveau sont ignorés. La valeur par défaut est LogLevelInfo.

Interrupteur de console

consoleLogEnabled

Contrôle l'affichage des journaux dans la console Xcode via NSLog.

Remarque

Si vous désactivez consoleLogEnabled, les journaux sont toujours distribués via les notifications aux observateurs, mais la sortie console est supprimée. Si vous désactivez logEnabled, toutes les demandes de journalisation sont ignorées et les observateurs ne reçoivent aucune notification.

Utilisation avancée : enregistrer un observateur de journal

Personnalisez le traitement des journaux en implémentant le protocole LogObserver :

// Create and register a file log observer
FileLogObserver *fileObserver = [[FileLogObserver alloc] init];
[[LogHub sharedHub] addObserver:fileObserver];

// Remove the observer when it is no longer needed
[[LogHub sharedHub] removeObserver:fileObserver];
Remarque

LogHub conserve une référence forte aux observateurs jusqu'à ce qu'ils soient explicitement supprimés à l'aide de removeObserver:. Vous devez appeler removeObserver: au moment approprié, par exemple dans dealloc ou viewWillDisappear:, pour éviter les références circulaires.

Utilisation avancée : panneau de journalisation

LogPanelSlot est un emplacement de débogage intégré qui affiche les informations de journal clés en temps réel dans la vue du lecteur :

// Enable the log panel (recommended only for debugging scenarios)
[AliPlayerKit setLogPanelEnabled:YES];

Interaction

Description

Cliquez sur la barre de titre

Développe ou réduit la zone de contenu des journaux.

Cliquez sur le bouton « Clear »

Efface les journaux affichés.

Appuyez longuement sur la zone de journalisation

Copie le contenu du journal dans le presse-papiers.

Remarque

Le panneau de journalisation affiche uniquement les journaux dont le niveau est Debug ou supérieur. Vous devez appeler setLogPanelEnabled: avant d'appeler rebuildSlots. Le panneau n'est pas visible dans le scénario Minimal.

Développement personnalisé

Protocole LogObserver

@protocol LogObserver <NSObject>

@required

/// Log output callback
/// @param logInfo The log information object, which contains the level, tag, message, and timestamp.
/// @warning This callback is executed in a background serial queue. Dispatch to the main thread to update the UI.
- (void)onLog:(LogInfo *)logInfo;

@end

Modèle de données LogInfo

Propriété

Type

Description

level

LogLevel

Niveau de journalisation (lecture seule).

tag

NSString *

Tag de journal (lecture seule).

message

NSString *

Contenu du message de journal (lecture seule).

timestamp

NSDate *

Horodatage de génération du journal (lecture seule).

threadName

NSString *

Nom du thread ayant généré le journal (lecture seule).

fileName

NSString *

Nom du fichier source, par exemple @"MyClass.m" (lecture seule).

line

NSInteger

Numéro de ligne du code source (lecture seule).

error

NSError *

Objet d'erreur associé, pouvant être nil (lecture seule).

Méthode

Description

formattedString

Récupère la chaîne de journal formatée.

initWithLevel:fileName:line:message:error:threadName:timestamp:

Initialiseur désigné.

initWithLevel:tag:message:

Initialiseur de commodité qui capture automatiquement l'horodatage et le nom du thread.

Format de sortie formaté :

2024-04-22 10:30:00.123 I/AliPlayerKit [version] [FileName:line] [threadName] : message

Si une erreur existe, une ligne supplémentaire est ajoutée :

Error: domain=xxx code=xxx userInfo=xxx

Exemple : observateur de journal personnalisé pour fichier

Voici une implémentation complète d'un observateur de journal pour fichier :

@interface MyFileLogObserver : NSObject <LogObserver>
- (instancetype)initWithLogDirectory:(NSString *)directory;
@end

@implementation MyFileLogObserver {
    NSString *_logFilePath;
    dispatch_queue_t _writeQueue;
    NSFileHandle *_fileHandle;
}

- (instancetype)initWithLogDirectory:(NSString *)directory {
    self = [super init];
    if (self) {
        _writeQueue = dispatch_queue_create("com.example.filelog",
                                            DISPATCH_QUEUE_SERIAL);
        [self setupLogFileAtDirectory:directory];
    }
    return self;
}

- (void)setupLogFileAtDirectory:(NSString *)directory {
    NSFileManager *fm = [NSFileManager defaultManager];
    if (![fm fileExistsAtPath:directory]) {
        [fm createDirectoryAtPath:directory
      withIntermediateDirectories:YES
                       attributes:nil
                            error:nil];
    }

    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    formatter.dateFormat = @"yyyy-MM-dd";
    NSString *fileName = [NSString stringWithFormat:@"player_%@.log",
                          [formatter stringFromDate:[NSDate date]]];
    _logFilePath = [directory stringByAppendingPathComponent:fileName];

    if (![fm fileExistsAtPath:_logFilePath]) {
        [fm createFileAtPath:_logFilePath contents:nil attributes:nil];
    }
    _fileHandle = [NSFileHandle fileHandleForWritingAtPath:_logFilePath];
    [_fileHandle seekToEndOfFile];
}

#pragma mark - LogObserver

- (void)onLog:(LogInfo *)logInfo {
    NSString *formatted = [logInfo formattedString];

    dispatch_async(_writeQueue, ^{
        NSString *line = [formatted stringByAppendingString:@"\n"];
        NSData *data = [line dataUsingEncoding:NSUTF8StringEncoding];
        @try {
            [self->_fileHandle writeData:data];
        } @catch (NSException *exception) {
            // Ignore write exceptions
        }
    });
}

- (void)dealloc {
    [_fileHandle closeFile];
}

@end
Remarque

Le rappel onLog: s'exécute dans une file d'attente série en arrière-plan. Toutefois, pour les opérations d'E/S de fichiers, nous vous recommandons d'utiliser une file d'attente d'écriture distincte afin d'éviter de bloquer la file d'attente de distribution des journaux. Un blocage de la file d'attente pourrait affecter d'autres observateurs.

Exemple : intégration complète

// AppDelegate.m
#import <AliPlayerKit/AliPlayerKit.h>

@interface AppDelegate ()
@property (nonatomic, strong) MyFileLogObserver *fileLogObserver;
@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application
    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    // 1. Initialize AliPlayerKit
    [AliPlayerKit setup];

    // 2. Configure the log system
#ifdef DEBUG
    [AliPlayerKit setLogLevel:LogLevelVerbose];
    [AliPlayerKit enableConsoleLog:YES];
    // Optional: Enable the log panel
    [AliPlayerKit setLogPanelEnabled:YES];
#else
    [AliPlayerKit setLogLevel:LogLevelInfo];
    [AliPlayerKit enableConsoleLog:NO];

    // 3. Register a file log observer (production environment only)
    NSString *logDir = [NSSearchPathForDirectoriesInDomains(
        NSDocumentDirectory, NSUserDomainMask, YES).firstObject
        stringByAppendingPathComponent:@"PlayerLogs"];
    self.fileLogObserver = [[MyFileLogObserver alloc] initWithLogDirectory:logDir];
    [[LogHub sharedHub] addObserver:self.fileLogObserver];
#endif

    return YES;
}

@end
Remarque

Le module PlayerKitUsages/UsageLogSystem fournit un exemple complet d'utilisation du système de journalisation. L'exemple inclut un FileLogObserver et une interface utilisateur pour l'affichage des journaux.

Bonnes pratiques

Recommandations de configuration par environnement

Environnement

Interrupteur principal

Console

Niveau

Observateur

Panneau de journalisation

Développement et débogage

OUI

OUI

Verbose

Facultatif (panneau UI)

Facultatif

Tests internes

OUI

OUI

Debug

Journalisation dans un fichier

NON

Environnement de production

OUI

NON

Info

Journalisation dans un fichier + rapport à distance

NON

Scénarios sensibles

NON

—

—

—

NON

Erreurs courantes

Erreur 1 : Mise à jour directe de l'interface utilisateur dans le rappel de l'observateur

// ✗ Incorrect: onLog: is executed in a background serial queue. Updating the UI directly will cause a crash.
- (void)onLog:(LogInfo *)logInfo {
    self.logLabel.text = [logInfo formattedString];  // Crash!
}

// ✓ Correct: Switch to the main thread to update the UI.
- (void)onLog:(LogInfo *)logInfo {
    NSString *formatted = [logInfo formattedString];
    dispatch_async(dispatch_get_main_queue(), ^{
        self.logLabel.text = formatted;
    });
}

Erreur 2 : Opérations de blocage synchrones dans l'observateur

// ✗ Incorrect: Synchronously writing to a file in the callback blocks the log dispatch queue.
- (void)onLog:(LogInfo *)logInfo {
    NSString *log = [logInfo formattedString];
    [log writeToFile:path atomically:YES encoding:NSUTF8StringEncoding error:nil];
}

// ✓ Correct: Asynchronously write to the file.
- (void)onLog:(LogInfo *)logInfo {
    NSString *log = [logInfo formattedString];
    dispatch_async(_writeQueue, ^{
        // Asynchronous write...
    });
}

Erreur 3 : Oubli de suppression de l'observateur, entraînant une référence circulaire

// ✗ Incorrect: LogHub strongly references the observer. Failure to remove it causes a circular reference.
- (void)viewDidLoad {
    [[LogHub sharedHub] addObserver:self];
    // Never released...
}

// ✓ Correct: Remove the observer at the end of the lifecycle.
- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    [[LogHub sharedHub] removeObserver:self];
}
Remarque

Contrairement au Dispatcher du système de notification, LogHub conserve une référence forte aux observateurs. Si vous n'appelez pas removeObserver:, l'observateur n'est pas libéré.

Référence API

Niveaux de journalisation (LogLevel)

Niveau

Valeur d'énumération

Valeur numérique

Description

Verbose

LogLevelVerbose

0

Le plus détaillé, destiné au développement et au débogage.

Debug

LogLevelDebug

1

Informations de débogage.

Info

LogLevelInfo

2

Niveau par défaut, recommandé pour la production.

Warn

LogLevelWarn

3

Problèmes potentiels.

Error

LogLevelError

4

Messages d'erreur.

None

LogLevelNone

100

Désactive tous les journaux.

Remarque

LogLevel.h fournit également la fonction inline LogLevelToString(), qui convertit un niveau de journalisation en une chaîne abrégée (V, D, I, W, E ou N).

API principale de LogHub

Propriété / Méthode

Type

Description

+sharedHub

Méthode de classe

Récupère l'instance singleton.

logEnabled

BOOL

Interrupteur principal de journalisation (par défaut : OUI).

logLevel

LogLevel

Niveau de journalisation (par défaut : LogLevelInfo).

consoleLogEnabled

BOOL

Interrupteur de console (par défaut : OUI).

v:msg:

Méthode d'instance

Génère un journal Verbose.

d:msg:

Méthode d'instance

Génère un journal Debug.

i:msg:

Méthode d'instance

Génère un journal Info.

w:msg:

Méthode d'instance

Génère un journal Warn.

e:msg:

Méthode d'instance

Génère un journal Error.

e:msg:error:

Méthode d'instance

Génère un journal Error avec un NSError.

log:tag:msg:

Méthode d'instance

Génère un journal au niveau spécifié.

logLevel:file:line:message:error:

Méthode d'instance

Méthode de journalisation principale (utilisée par les macros SLOG).

addObserver:

Méthode d'instance

Ajoute un observateur (référence forte, aucun effet en cas d'ajout répété).

removeObserver:

Méthode d'instance

Supprime un observateur.

+levelToString:

Méthode de classe

Convertit un niveau en chaîne (V/D/I/W/E/N).

+stringToLevel:

Méthode de classe

Convertit une chaîne en niveau (insensible à la casse, renvoie LogLevelInfo si non reconnu).

API de raccourci de journalisation AliPlayerKit

Méthode

Description

+setLogLevel:

Définit le niveau de journalisation (doit être appelé après setup).

+logLevel

Récupère le niveau de journalisation actuel.

+enableConsoleLog:

Active ou désactive la sortie des journaux dans la console.

+isConsoleLogEnabled

Vérifie si la journalisation console est activée.

+setDebugModeEnabled:

Active ou désactive le mode débogage.

+isDebugModeEnabled

Vérifie si le mode débogage est activé.

+setLogPanelEnabled:

Active ou désactive l'emplacement du panneau de journalisation.

+isLogPanelEnabled

Vérifie si le panneau de journalisation est activé.

Macros d'aide SLOG

Macro

Niveau

Forme développée

SLOGV(fmt, ...)

Verbose

[[LogHub sharedHub] logLevel:LogLevelVerbose file:@(__FILE_NAME__) line:__LINE__ message:... error:nil]

SLOGD(fmt, ...)

Debug

Identique ci-dessus, avec le niveau Debug.

SLOGI(fmt, ...)

Info

Identique ci-dessus, avec le niveau Info.

SLOGW(fmt, ...)

Warn

Identique ci-dessus, avec le niveau Warn.

SLOGE(fmt, ...)

Error

Identique ci-dessus, avec le niveau Error.

Propriétés LogInfo

Propriété

Type

Description

level

LogLevel

Niveau de journalisation.

tag

NSString *

Tag de journal.

message

NSString *

Contenu du message de journal.

timestamp

NSDate *

Horodatage de génération du journal.

threadName

NSString *

Nom du thread.

fileName

NSString *

Nom du fichier source.

line

NSInteger

Numéro de ligne du code source.

error

NSError *

Objet d'erreur associé (nullable).

formattedString

Méthode

Récupère la chaîne de journal formatée.

Protocole LogObserver

Méthode

Obligatoire

Description

onLog:

Oui (@required)

Rappel de sortie de journal, exécuté dans une file d'attente série en arrière-plan.