Coverage Report

Created: 2026-03-10 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/S2OPC/src/Common/helpers/sopc_logger.c
Line
Count
Source
1
/*
2
 * Licensed to Systerel under one or more contributor license
3
 * agreements. See the NOTICE file distributed with this work
4
 * for additional information regarding copyright ownership.
5
 * Systerel licenses this file to you under the Apache
6
 * License, Version 2.0 (the "License"); you may not use this
7
 * file except in compliance with the License. You may obtain
8
 * a copy of the License at
9
 *
10
 *   http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing,
13
 * software distributed under the License is distributed on an
14
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
 * KIND, either express or implied.  See the License for the
16
 * specific language governing permissions and limitations
17
 * under the License.
18
 */
19
20
#include "sopc_logger.h"
21
22
#include <stdio.h>
23
#include <string.h>
24
25
#include "sopc_array.h"
26
#include "sopc_assert.h"
27
#include "sopc_common_constants.h"
28
#include "sopc_date_time.h"
29
#include "sopc_filesystem.h"
30
#include "sopc_helper_string.h"
31
#include "sopc_mem_alloc.h"
32
33
static const char* traceName = "Trace";
34
static char* filePath = NULL;
35
36
static SOPC_Log_Instance* commonTrace = NULL;
37
static SOPC_Log_Instance* clientServerTrace = NULL;
38
static SOPC_Log_Instance* pubSubTrace = NULL;
39
40
// User section logs:
41
typedef SOPC_Log_Instance* UserLogElement;
42
43
// Array containing all user log sections managed by toolkit.
44
static SOPC_Array* userLogArray = NULL;
45
static void userLogArray_Free_Func(void* data)
46
0
{
47
0
    UserLogElement elt = (UserLogElement) data;
48
0
    SOPC_Log_ClearInstance(&elt);
49
0
}
50
51
/*
52
 * \brief Initializes the file logger and create the necessary log file(s), assuming that commonTrace is the master
53
 * instance.
54
 *
55
 * \param pLogInst  An existing log instance used to print in the same log file
56
57
 *
58
 * */
59
static bool SOPC_Logger_InstancesInitialize(void);
60
61
bool SOPC_Logger_Initialize(const SOPC_Log_Configuration* const logConfiguration)
62
0
{
63
0
    if (NULL != filePath)
64
0
    {
65
        // Already configured.
66
0
        return false;
67
0
    }
68
69
0
    const SOPC_Log_System logSystem = (NULL == logConfiguration) ? SOPC_LOG_SYSTEM_NO_LOG : logConfiguration->logSystem;
70
71
0
    bool result = false;
72
73
0
    char* uniqueLogPrefix = SOPC_Time_GetStringOfCurrentTimeUTC(true);
74
0
    SOPC_ASSERT(NULL != uniqueLogPrefix);
75
76
    // Format is <date>_<traceName> : +2 = '_' and '\0'
77
0
    filePath = (char*) SOPC_Malloc(strlen(traceName) + strlen(uniqueLogPrefix) + 2);
78
0
    SOPC_ASSERT(NULL != filePath);
79
0
    sprintf(filePath, "%s_%s", traceName, uniqueLogPrefix);
80
0
    SOPC_Free(uniqueLogPrefix);
81
82
0
    switch (logSystem)
83
0
    {
84
0
    case SOPC_LOG_SYSTEM_FILE:
85
0
    {
86
0
        const SOPC_LogSystem_File_Configuration* logCfg = &logConfiguration->logSysConfig.fileSystemLogConfig;
87
0
        SOPC_CircularLogFile_Configuration conf = {.logDirPath = logCfg->logDirPath,
88
0
                                                   .logFileName = filePath,
89
0
                                                   .logMaxBytes = logCfg->logMaxBytes,
90
0
                                                   .logMaxFiles = logCfg->logMaxFiles};
91
0
        commonTrace = SOPC_Log_CreateFileInstance(&conf, "Common");
92
0
        result = SOPC_Logger_InstancesInitialize();
93
94
0
        break;
95
0
    }
96
0
    case SOPC_LOG_SYSTEM_USER:
97
0
        commonTrace = SOPC_Log_CreateUserInstance("Common", logConfiguration->logSysConfig.userSystemLogConfig.doLog);
98
0
        result = SOPC_Logger_InstancesInitialize();
99
0
        break;
100
0
    case SOPC_LOG_SYSTEM_NO_LOG:
101
0
        result = true;
102
0
        break;
103
0
    default:
104
0
        result = false;
105
0
        break;
106
0
    }
107
0
    if (SOPC_LOG_SYSTEM_NO_LOG != logSystem)
108
0
    {
109
0
        if (result)
110
0
        {
111
0
            SOPC_Logger_SetTraceLogLevel(logConfiguration->logLevel);
112
0
        }
113
0
        else
114
0
        {
115
            /* Status stays OK given that we don't have other alternatives for now */
116
0
            fprintf(stderr, "ERROR: S2OPC Logs initialization failed!\n");
117
0
        }
118
0
    }
119
0
    return result;
120
0
}
121
122
SOPC_Log_Instance* SOPC_Logger_AddUserInstance(const char* category)
123
0
{
124
0
    SOPC_Log_Instance* result = NULL;
125
0
    if (NULL == userLogArray)
126
0
    {
127
0
        userLogArray = SOPC_Array_Create(sizeof(UserLogElement), 1, &userLogArray_Free_Func);
128
0
    }
129
0
    if (NULL != userLogArray)
130
0
    {
131
0
        result = SOPC_Log_CreateInstanceAssociation(commonTrace, category);
132
0
    }
133
0
    if (result != NULL)
134
0
    {
135
0
        const bool appendOk = SOPC_Array_Append_Values(userLogArray, result, 1);
136
0
        if (!appendOk)
137
0
        {
138
0
            SOPC_Log_ClearInstance(&result);
139
0
            result = NULL;
140
0
        }
141
0
    }
142
0
    return result;
143
0
}
144
145
static bool SOPC_Logger_InstancesInitialize(void)
146
0
{
147
0
    bool result = false;
148
0
    if (commonTrace != NULL)
149
0
    {
150
0
        result = true;
151
0
        clientServerTrace = SOPC_Log_CreateInstanceAssociation(commonTrace, "ClientServer");
152
0
        if (clientServerTrace == NULL)
153
0
        {
154
0
            SOPC_CONSOLE_PRINTF("WARNING: ClientServer log creation failed, no ClientServer log will be recorded !");
155
0
        }
156
157
0
        pubSubTrace = SOPC_Log_CreateInstanceAssociation(commonTrace, "PubSub");
158
0
        if (pubSubTrace == NULL)
159
0
        {
160
0
            SOPC_CONSOLE_PRINTF("WARNING: PubSub log creation failed, no PubSub log will be recorded !");
161
0
        }
162
0
    }
163
0
    else
164
0
    {
165
0
        SOPC_CONSOLE_PRINTF("WARNING: log creation failed, no log will be recorded !\n");
166
0
    }
167
0
    return result;
168
0
}
169
170
void SOPC_Logger_SetTraceLogLevel(SOPC_Log_Level level)
171
0
{
172
0
    if (commonTrace != NULL)
173
0
    {
174
0
        SOPC_Log_SetLogLevel(commonTrace, level);
175
0
    }
176
0
    if (clientServerTrace != NULL)
177
0
    {
178
0
        SOPC_Log_SetLogLevel(clientServerTrace, level);
179
0
    }
180
0
    if (pubSubTrace != NULL)
181
0
    {
182
0
        SOPC_Log_SetLogLevel(pubSubTrace, level);
183
0
    }
184
0
}
185
186
SOPC_Log_Level SOPC_Logger_GetTraceLogLevel(void)
187
0
{
188
0
    return SOPC_Log_GetLogLevel(commonTrace);
189
0
}
190
191
void SOPC_Logger_SetConsoleOutput(bool activate)
192
0
{
193
0
    if (commonTrace != NULL)
194
0
    {
195
0
        SOPC_Log_SetConsoleOutput(commonTrace, activate);
196
0
    }
197
0
    if (clientServerTrace != NULL)
198
0
    {
199
0
        SOPC_Log_SetConsoleOutput(clientServerTrace, activate);
200
0
    }
201
0
    if (pubSubTrace != NULL)
202
0
    {
203
0
        SOPC_Log_SetConsoleOutput(pubSubTrace, activate);
204
0
    }
205
0
}
206
207
static void logger_Trace(SOPC_Log_Module logModule, SOPC_Log_Level logLevel, const char* format, va_list args)
208
480
{
209
480
    switch (logModule)
210
480
    {
211
54
    case SOPC_LOG_MODULE_COMMON:
212
54
        if (commonTrace != NULL)
213
0
        {
214
0
            SOPC_Log_VTrace(commonTrace, logLevel, format, args);
215
0
        }
216
54
        break;
217
426
    case SOPC_LOG_MODULE_CLIENTSERVER:
218
426
        if (clientServerTrace != NULL)
219
0
        {
220
0
            SOPC_Log_VTrace(clientServerTrace, logLevel, format, args);
221
0
        }
222
426
        break;
223
0
    case SOPC_LOG_MODULE_PUBSUB:
224
0
        if (pubSubTrace != NULL)
225
0
        {
226
0
            SOPC_Log_VTrace(pubSubTrace, logLevel, format, args);
227
0
        }
228
0
        break;
229
0
    default:
230
0
        break;
231
480
    }
232
480
}
233
234
void SOPC_Logger_TraceError(SOPC_Log_Module logModule, const char* format, ...)
235
480
{
236
480
    va_list args;
237
480
    va_start(args, format);
238
480
    logger_Trace(logModule, SOPC_LOG_LEVEL_ERROR, format, args);
239
480
    va_end(args);
240
480
}
241
242
void SOPC_Logger_TraceWarning(SOPC_Log_Module logModule, const char* format, ...)
243
0
{
244
0
    va_list args;
245
0
    va_start(args, format);
246
0
    logger_Trace(logModule, SOPC_LOG_LEVEL_WARNING, format, args);
247
0
    va_end(args);
248
0
}
249
250
void SOPC_Logger_TraceInfo(SOPC_Log_Module logModule, const char* format, ...)
251
0
{
252
0
    va_list args;
253
0
    va_start(args, format);
254
0
    logger_Trace(logModule, SOPC_LOG_LEVEL_INFO, format, args);
255
0
    va_end(args);
256
0
}
257
258
void SOPC_Logger_TraceDebug(SOPC_Log_Module logModule, const char* format, ...)
259
0
{
260
0
    va_list args;
261
0
    va_start(args, format);
262
0
    logger_Trace(logModule, SOPC_LOG_LEVEL_DEBUG, format, args);
263
0
    va_end(args);
264
0
}
265
266
void SOPC_Logger_Clear(void)
267
0
{
268
0
    if (userLogArray == NULL)
269
0
    {
270
0
        SOPC_Array_Delete(userLogArray);
271
0
        userLogArray = NULL;
272
0
    }
273
0
    if (clientServerTrace != NULL)
274
0
    {
275
0
        SOPC_Log_ClearInstance(&clientServerTrace);
276
0
    }
277
0
    if (pubSubTrace != NULL)
278
0
    {
279
0
        SOPC_Log_ClearInstance(&pubSubTrace);
280
0
    }
281
0
    if (commonTrace != NULL)
282
0
    {
283
0
        SOPC_Log_ClearInstance(&commonTrace);
284
0
    }
285
0
    SOPC_Free(filePath);
286
    filePath = NULL;
287
0
}