Using Logging and Tracing on the Multiservices PIC

As background for the functionality shown in this topic, see IP Socket-Based Inter-Process Communication, Using the libconn Library For Intermodule Communications, and Logging and Tracing on the Multiservices PIC.

How Applications Use Logging and Tracing

When your application's management component on the Routing Engine calls junos_app_init(), the system populates a structure, daemon_trace_file_options_t, with trace information. The structure is declared as follows:

typedef struct pic_daemon_trace_file_options_s {
    char dtf_name[MAXPATHLEN];    /* Trace file name */
    u_int32_t dtf_size;           /* Size of trace file */
    u_int32_t dtf_count;          /* Maximum number of files desired */
    boolean dtf_wreadable;        /* Allow any user to read */
    u_int32_t dtf_trace_level;    /* Trace level */
} pic_daemon_trace_file_options_t;

The steps your application takes are as follows:

Example of Using Logging and Tracing

This test code includes a component on the Routing Engine that obtains the trace information and calls pconn_server_send() to send the information to the PIC, and a component on the PIC that configures the tracing infrastructure and logs test trace messages. The code has been slightly edited for simplicity.

Trace Server on the Routing Engine

The component on the Routing Engine is as follows:

/* Test program for Logging and Tracing on the Multiservices PIC. Acts as server
 * running on the Routing Engine.
 */
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netdb.h>
#include <unistd.h>
#include <ctype.h>

#include <isc/eventlib.h>
#include <jnx/bits.h>
#include <jnx/junos_init.h>
#include <string.h>
#include <jnx/aux_types.h>
#include <jnx/bits.h>
#include <jnx/patricia.h>
#include <jnx/pconn.h>
#include <jnx/parse_ip.h>
#include <syslog.h>
#include <errno.h>
#include <jnx/trace.h>
#include <jnx/junos_trace.h>
#include <helpers/trace_util.h>
#include <jnx/junos_trace_priv.h>

#define SERVER_PORT 9099

evContext ctxt;
char msg[1024 * 12];
pconn_server_params_t server_params;
pconn_server_t  *server;
pconn_client_t  *client;
pconn_session_t *client_session;
pic_daemon_trace_file_options_t *pic_trace_file_info;
int size;

#define MSG_LOG_TRACE_INFO 1
#define TEST_TRACE_FILE "/var/log/trialtrace.log"

static void
set_trace_file_options (void)
{
     /* Trace configuration */
    daemon_trace_file_options_t *dtf_options = junos_trace_get_dtf_options();
    strcpy(dtf_options->dtf_name, TEST_TRACE_FILE);
    dtf_options->dtf_trace_file = trace_file_open(NULL, TEST_TRACE_FILE, 
						  1000000, 1);
    strcpy(dtf_options->dtf_name, TEST_TRACE_FILE);
    dtf_options->dtf_size = 1000000;
    dtf_options->dtf_count = 1;
    dtf_options->dtf_trace_level = TRACE_ALL;
    trace_flag_set(dtf_options->dtf_trace_file, TRACE_ALL);
    dtf_options->dtf_no_remote_trace = TRUE;
   
	  dtf_options->dtf_trace_level);
}


static status_t
server_msg_handler (pconn_session_t * session __unused,
		    ipc_msg_t * ipc_msg __unused, void * cookie __unused)
{
    int status;
    int retval;

    printf("server msg received:type %d, subtype %d, length %d\n",
           ipc_msg->type, ipc_msg->subtype, ipc_msg->length);

    
    /* 
     * Obtains the trace configuration to be sent to the MS PIC
     */
    retval = junos_trace_get_pic_trace_file_info(&pic_trace_file_info, &size);

    if (retval != 0) {
	    printf("junos_trace_get_pic_trace_file_info API returned failure\n");
	    return retval;
    }
    
    printf("junos_trace_get_pic_trace_file_info API returned success\n");

     /* Send the information to the client on the PIC*/
    status = pconn_server_send(session, MSG_LOG_TRACE_INFO,
			   pic_trace_file_info, size);

    if (status != PCONN_OK) {
	      pconn_session_close(session);
        printf("(%s:%d):pconn_server_send failed\n");
     }

    if (retval == 0) {
	  /* Call the API to free the allocated structure */
    	junos_trace_free_pic_trace_file_info(pic_trace_file_info);
    }
	 return EOK;
}

static void
server_event_handler (pconn_session_t * session,
		      pconn_event_t event, void * cookie __unused)
{
    unsigned int status;
    int retval;

    switch (event) {
    case PCONN_EVENT_ESTABLISHED:
        client_session = session;
        break;

    case PCONN_EVENT_SHUTDOWN:
    case PCONN_EVENT_FAILED:
        client_session = NULL;
        return;

    default:
        break;
    }

    if (!client_session) {
     	pconn_session_close(session);
      return;
    }

    /*
     * Obtain the trace configuration 
     */
    retval = junos_trace_get_pic_trace_file_info(&pic_trace_file_info, &size);

    if (retval != 0) {
	    junos_trace(TRACE_LOG_ERR, "junos_trace_get_pic_trace_file_info API "
		    "returned failure\n");
    	printf("junos_trace_get_pic_trace_file_info API returned failure\n");
    	return;
    }

    junos_trace(LOG_INFO, "junos_trace_get_pic_trace_file_info API "
		"returned success\n");
    printf("junos_trace_get_pic_trace_file_info API returned success\n");
    
    /* Send the trace configuration to the client */
    status = pconn_server_send(session, MSG_LOG_TRACE_INFO,
			       pic_trace_file_info, size);

    if (status != PCONN_OK) {
      	pconn_session_close(session);
        printf("%s:%d: pconn_server_send failed\n");
    }
    
    if (retval == 0) {
  	/* Call the API to free the allocated structure */
    	junos_trace_free_pic_trace_file_info(pic_trace_file_info);
    }

   
}

static status_t
server_func (void)
{
    pconn_server_params_t params;

    memset(&params, 0, sizeof(params));

    set_trace_file_options();

    params.pconn_port            = SERVER_PORT;
    params.pconn_max_connections = 2;
    params.pconn_event_handler   = server_event_handler;

    errno = 0; 
    server = pconn_server_create(&params, ctxt,
                                 server_msg_handler, NULL);

    if (server == NULL) {
      	printf("%s(%d): server init failed...: %s\n", strerror(errno));
        syslog(LOG_ERR, "%s:server init failed");
        return EFAIL;
    }
    syslog(LOG_ERR, "%s:server init successful");
    return EOK;
}

static void
server_quit(int signo __unused)
{
    if (server) {
        pconn_server_shutdown(server);
        server = NULL;
    }
    if (client_session) {
	      pconn_session_close(client_session);
        client_session = NULL;
    }
}

static int
server_init (evContext ctx)
{
    ctxt = ctx;
    
    signal(SIGHUP, SIG_IGN);
    signal(SIGPIPE, SIG_IGN);
    signal(SIGTERM, server_quit);

    if (server_func() == EOK) {
        return 1;
    }
    return 0;
}

int
main (int argc, char **argv)
{
    int ret = 0;
    junos_sdk_app_ctx_t app_ctxt;

    /* create an application context */
    app_ctxt = junos_create_app_ctx(argc, argv, "testlogtrace", NULL, "", 0);

    if (app_ctxt == NULL) {
        syslog(LOG_ERR, "%s:app cb create failed");
        return -1;
    }

    /* set init callback */
    if ((ret = junos_set_app_cb_init(app_ctxt, server_init)) < 0) {
        syslog(LOG_ERR, "%s:app cb init failed");
        goto cleanup;
    }
    syslog(LOG_ERR, "%s:app cb init successful");
    ret = junos_app_init(app_ctxt);

cleanup:
    junos_destroy_app_ctx(app_ctxt);
    return ret;
}

Trace Client on the Multiservices PIC

The code in the control component on the PIC is as follows:

/* Test program for Logging and Tracing on PIC. Acts as a client
 * connecting to the server running on the Routing Engine.
 */
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netdb.h>
#include <unistd.h>
#include <ctype.h>

#include <isc/eventlib.h>
#include <jnx/bits.h>
#include <string.h>
#include <jnx/aux_types.h>
#include <jnx/bits.h>
#include <jnx/trace.h>
#include <jnx/junos_trace.h>
#include <jnx/junos_trace_mpsdk.h>
#include <jnx/pconn.h>
#include <jnx/parse_ip.h>
#include <syslog.h>
#include <errno.h>
#include <isc/eventlib.h>
#include <jnx/mpsdk.h>
#include <jnx/msp_syslog.h>


#define DNAME_TESTLOGTRACE_CLIENT    "testlogtraceclient"
#define SERVER_PORT 9099

/* Global variables */
evContext ctxt;
pconn_client_t  *client;


static status_t
client_msg_handler (pconn_client_t * session __unused,
		    ipc_msg_t * ipc_msg __unused, void * cookie __unused)
{
    pic_syslog_conf_t *conf = NULL;
    int i;


#define MSG_LOG_TRACE_INFO 1
#define NUM_TRACE_MSGS 5

    int status;
    pic_daemon_trace_file_options_t *pic_trace_file_info;
    uint32_t size = 0;

    printf("client msg received:type %d, subtype %d, length %d\n",
           ipc_msg->type, ipc_msg->subtype, ipc_msg->length);

    if (ipc_msg->subtype != MSG_LOG_TRACE_INFO) {
	      printf("(%s:%d): Invalid message received\n");
	      return -1;
    }

   if (ipc_msg->length <= 0) {
	     printf("(%s:%d): Invalid message received\n");
	     return -1;
    }

    pic_trace_file_info = (pic_daemon_trace_file_options_t *)ipc_msg->data;
 
    /* 
     * Configures the tracing infrastructure after receiving tracing 
     * information from the server on the Routing Engine 
     */
    status = junos_trace_set_pic_trace_file_info(pic_trace_file_info);

    if (status == -1) {
     	printf("%s(%d): Unable to initialize trace configuration\n");
    } else {
     	printf("junos_trace_set_pic_trace_file_info API returned success\n");
	
	  /* 
	   * Tests whether "LOG_TRACE" is configured and then constructs
	   * the trace message */
	  status = junos_trace_check_trace_level(LOG_INFO);
  	if (status) {
	    printf("LOG_INFO is configured\n");
    	    junos_trace( LOG_INFO, "%s(%d): Initialized trace configuration);
	    for (i = 0; i < NUM_TRACE_MSGS; i++) {
    	    junos_trace( LOG_INFO, "%s(%d): Test Message: %d\n", __func__,  __LINE__, i);
	    }
  	} else {
	    printf("LOG_INFO is not configured\n");
	  }
	

    /* Obtains the configured syslog facilities and actions */
    status = junos_syslog_get_config(&conf);

    if (status == -1) {
	    printf("%s(%d):failed to get syslog config\n");
    } else {
	    printf("%s(%d): read syslog config successfully\n");
    }

    openlog(DNAME_TESTLOGTRACE_CLIENT, LOG_PID, LOG_DAEMON);
    
    logging_set_mode(LOGGING_SYSLOG|LOGGING_STDERR);

    
    /* 
     * Check whether the facility "daemon" and priority level "info" is 
     * configured 
     */
    status = junos_syslog_facility_level_check(conf, LOG_DAEMON, LOG_INFO);

    if (status == -1) {
       syslog(LOG_ERR, "daemon.info not configured\n");
	     printf("%s(%d):daemon.info not configured\n");
    } else {
	     syslog(LOG_INFO, "daemon.info configured\n");
	     printf("%s(%d): daemon.info configured\n");
    }
    
 
    /* Call the API to free the allocated memory */
    junos_syslog_pic_syslog_conf_free(conf);

 
    return EOK;
}

static void
client_event_handler (pconn_client_t * session,
		      pconn_event_t event, void * cookie __unused)
{

    syslog(LOG_ERR, "client event %d received", event);
    switch (event) {
    case PCONN_EVENT_ESTABLISHED:
        break;

    case PCONN_EVENT_SHUTDOWN:
    case PCONN_EVENT_FAILED:
        break;

    default:
        break;
    }
}

static status_t
client_func (void)
{
    pconn_client_params_t params;
    memset(&params, 0, sizeof(params));
    
    params.pconn_peer_info.ppi_peer_type = PCONN_PEER_TYPE_RE; 
    params.pconn_port = SERVER_PORT;
    params.pconn_num_retries = 1;
    params.pconn_event_handler   = client_event_handler;
    client = pconn_client_connect_async(&params, ctxt,
                                 client_msg_handler, &ctxt);
    if (client == NULL) {
        syslog(LOG_ERR, "%s:client init failed");
        return EFAIL;
    }
    syslog(LOG_ERR, "%s:client init successful"_);
    return EOK;
}

static void
client_quit(int signo __unused)
{
    pconn_client_close(client);
    client = NULL;
}


static int
client_init (evContext ctx)
{
    ctxt = ctx;
    signal(SIGTERM, client_quit);
    signal(SIGHUP, SIG_IGN);
    signal(SIGPIPE, SIG_IGN);

    if (client_func() == EOK) {
        return 0;
    }
    return 1;
}

int
main (int argc, char **argv)
{
    msp_daemon_init(argc, argv, client_init, DNAME_TESTLOGTRACE_CLIENT, TRUE);
    return 0;
}

2007-2009 Juniper Networks, Inc. All rights reserved. The information contained herein is confidential information of Juniper Networks, Inc., and may not be used, disclosed, distributed, modified, or copied without the prior written consent of Juniper Networks, Inc. in an express license. This information is subject to change by Juniper Networks, Inc. Juniper Networks, the Juniper Networks logo, and JUNOS are registered trademarks of Juniper Networks, Inc. in the United States and other countries. All other trademarks, service marks, registered trademarks, or registered service marks are the property of their respective owners.
Generated on Sun May 30 20:26:47 2010 for Juniper Networks Partner Solution Development Platform JUNOS SDK 10.2R1 by Doxygen 1.4.5