Search in sources :

Example 6 with Journal

use of org.graylog2.shared.journal.Journal in project graylog2-server by Graylog2.

the class JournalReader method run.

@Override
protected void run() throws Exception {
    try {
        requestedReadCount = metricRegistry.register(name(this.getClass(), "requestedReadCount"), new HdrHistogram(processBuffer.getRingBufferSize() + 1, 3));
    } catch (IllegalArgumentException e) {
        log.warn("Metric already exists", e);
        throw e;
    }
    while (isRunning()) {
        // TODO interfere with reading if we are not 100% certain we should be reading, see #listenForLifecycleChanges
        if (!shouldBeReading) {
            Uninterruptibles.sleepUninterruptibly(100, MILLISECONDS);
            // don't read immediately, but check if we should be shutting down.
            continue;
        }
        // approximate count to read from the journal to backfill the processing chain
        final long remainingCapacity = processBuffer.getRemainingCapacity();
        requestedReadCount.update(remainingCapacity);
        final List<Journal.JournalReadEntry> encodedRawMessages = journal.read(remainingCapacity);
        if (encodedRawMessages.isEmpty()) {
            log.debug("No messages to read from Journal, waiting until the writer adds more messages.");
            // block until something is written to the journal again
            try {
                readBlocked.inc();
                journalFilled.acquire();
            } catch (InterruptedException ignored) {
                // this can happen when we are blocked but the system wants to shut down. We don't have to do anything in that case.
                continue;
            }
            log.debug("Messages have been written to Journal, continuing to read.");
            // we don't care how many messages were inserted in the meantime, we'll read all of them eventually
            journalFilled.drainPermits();
        } else {
            readMessages.mark(encodedRawMessages.size());
            log.debug("Processing {} messages from journal.", encodedRawMessages.size());
            for (final Journal.JournalReadEntry encodedRawMessage : encodedRawMessages) {
                final RawMessage rawMessage = RawMessage.decode(encodedRawMessage.getPayload(), encodedRawMessage.getOffset());
                if (rawMessage == null) {
                    // never insert null objects into the ringbuffer, as that is useless
                    log.error("Found null raw message!");
                    journal.markJournalOffsetCommitted(encodedRawMessage.getOffset());
                    continue;
                }
                processBuffer.insertBlocking(rawMessage);
            }
        }
    }
    log.info("Stopping.");
}
Also used : HdrHistogram(org.graylog2.shared.metrics.HdrHistogram) RawMessage(org.graylog2.plugin.journal.RawMessage)

Example 7 with Journal

use of org.graylog2.shared.journal.Journal in project graylog2-server by Graylog2.

the class KafkaJournal method write.

/**
     * Writes the list of entries to the journal.
     *
     * @param entries journal entries to be written
     * @return the last position written to in the journal
     */
@Override
public long write(List<Entry> entries) {
    try (Timer.Context ignored = writeTime.time()) {
        long payloadSize = 0L;
        long messageSetSize = 0L;
        long lastWriteOffset = 0L;
        final List<Message> messages = new ArrayList<>(entries.size());
        for (final Entry entry : entries) {
            final byte[] messageBytes = entry.getMessageBytes();
            final byte[] idBytes = entry.getIdBytes();
            payloadSize += messageBytes.length;
            final Message newMessage = new Message(messageBytes, idBytes);
            // Calculate the size of the new message in the message set by including the overhead for the log entry.
            final int newMessageSize = MessageSet.entrySize(newMessage);
            if (newMessageSize > maxMessageSize) {
                writeDiscardedMessages.mark();
                LOG.warn("Message with ID <{}> is too large to store in journal, skipping! (size: {} bytes / max: {} bytes)", new String(idBytes, StandardCharsets.UTF_8), newMessageSize, maxMessageSize);
                payloadSize = 0;
                continue;
            }
            // list of message to avoid a MessageSetSizeTooLargeException.
            if ((messageSetSize + newMessageSize) > maxSegmentSize) {
                if (LOG.isDebugEnabled()) {
                    LOG.debug("Flushing {} bytes message set with {} messages to avoid overflowing segment with max size of {} bytes", messageSetSize, messages.size(), maxSegmentSize);
                }
                lastWriteOffset = flushMessages(messages, payloadSize);
                // Reset the messages list and size counters to start a new batch.
                messages.clear();
                messageSetSize = 0;
                payloadSize = 0;
            }
            messages.add(newMessage);
            messageSetSize += newMessageSize;
            if (LOG.isTraceEnabled()) {
                LOG.trace("Message {} contains bytes {}", bytesToHex(idBytes), bytesToHex(messageBytes));
            }
        }
        // Flush the rest of the messages.
        if (messages.size() > 0) {
            lastWriteOffset = flushMessages(messages, payloadSize);
        }
        return lastWriteOffset;
    }
}
Also used : HdrTimer(org.graylog2.shared.metrics.HdrTimer) Timer(com.codahale.metrics.Timer) Message(kafka.message.Message) ArrayList(java.util.ArrayList)

Example 8 with Journal

use of org.graylog2.shared.journal.Journal in project graylog2-server by Graylog2.

the class KafkaJournal method read.

public List<JournalReadEntry> read(long readOffset, long requestedMaximumCount) {
    // Always read at least one!
    final long maximumCount = Math.max(1, requestedMaximumCount);
    long maxOffset = readOffset + maximumCount;
    if (shuttingDown) {
        return Collections.emptyList();
    }
    final List<JournalReadEntry> messages = new ArrayList<>(Ints.saturatedCast(maximumCount));
    try (Timer.Context ignored = readTime.time()) {
        final long logStartOffset = getLogStartOffset();
        if (readOffset < logStartOffset) {
            LOG.info("Read offset {} before start of log at {}, starting to read from the beginning of the journal.", readOffset, logStartOffset);
            readOffset = logStartOffset;
            maxOffset = readOffset + maximumCount;
        }
        LOG.debug("Requesting to read a maximum of {} messages (or 5MB) from the journal, offset interval [{}, {})", maximumCount, readOffset, maxOffset);
        // TODO benchmark and make read-ahead strategy configurable for performance tuning
        final MessageSet messageSet = kafkaLog.read(readOffset, 5 * 1024 * 1024, Option.<Object>apply(maxOffset)).messageSet();
        final Iterator<MessageAndOffset> iterator = messageSet.iterator();
        long firstOffset = Long.MIN_VALUE;
        long lastOffset = Long.MIN_VALUE;
        long totalBytes = 0;
        while (iterator.hasNext()) {
            final MessageAndOffset messageAndOffset = iterator.next();
            if (firstOffset == Long.MIN_VALUE)
                firstOffset = messageAndOffset.offset();
            // always remember the last seen offset for debug purposes below
            lastOffset = messageAndOffset.offset();
            final byte[] payloadBytes = ByteBufferUtils.readBytes(messageAndOffset.message().payload());
            if (LOG.isTraceEnabled()) {
                final byte[] keyBytes = ByteBufferUtils.readBytes(messageAndOffset.message().key());
                LOG.trace("Read message {} contains {}", bytesToHex(keyBytes), bytesToHex(payloadBytes));
            }
            totalBytes += payloadBytes.length;
            messages.add(new JournalReadEntry(payloadBytes, messageAndOffset.offset()));
            // remember where to read from
            nextReadOffset = messageAndOffset.nextOffset();
        }
        if (messages.isEmpty()) {
            LOG.debug("No messages available to read for offset interval [{}, {}).", readOffset, maxOffset);
        } else {
            LOG.debug("Read {} messages, total payload size {}, from journal, offset interval [{}, {}], requested read at {}", messages.size(), totalBytes, firstOffset, lastOffset, readOffset);
        }
    } catch (OffsetOutOfRangeException e) {
        // This is fine, the reader tries to read faster than the writer committed data. Next read will get the data.
        LOG.debug("Offset out of range, no messages available starting at offset {}", readOffset);
    } catch (Exception e) {
        // sigh.
        if (shuttingDown) {
            LOG.debug("Caught exception during shutdown, ignoring it because we might have been blocked on a read.");
            return Collections.emptyList();
        }
        //noinspection ConstantConditions
        if (e instanceof ClosedByInterruptException) {
            LOG.debug("Interrupted while reading from journal, during shutdown this is harmless and ignored.", e);
        } else {
            throw e;
        }
    }
    readMessages.mark(messages.size());
    return messages;
}
Also used : ArrayList(java.util.ArrayList) MessageAndOffset(kafka.message.MessageAndOffset) ClosedByInterruptException(java.nio.channels.ClosedByInterruptException) SyncFailedException(java.io.SyncFailedException) AccessDeniedException(java.nio.file.AccessDeniedException) KafkaException(kafka.common.KafkaException) OffsetOutOfRangeException(kafka.common.OffsetOutOfRangeException) IOException(java.io.IOException) MessageSet(kafka.message.MessageSet) ByteBufferMessageSet(kafka.message.ByteBufferMessageSet) ClosedByInterruptException(java.nio.channels.ClosedByInterruptException) HdrTimer(org.graylog2.shared.metrics.HdrTimer) Timer(com.codahale.metrics.Timer) OffsetOutOfRangeException(kafka.common.OffsetOutOfRangeException)

Example 9 with Journal

use of org.graylog2.shared.journal.Journal in project graylog2-server by Graylog2.

the class MessageFilterChainProcessorTest method testHandleMessage.

@Test
public void testHandleMessage() {
    MessageFilter filterOnlyFirst = new MessageFilter() {

        private boolean filterOut = true;

        @Override
        public boolean filter(Message msg) {
            if (filterOut) {
                msg.setFilterOut(true);
                filterOut = false;
                return true;
            }
            return false;
        }

        @Override
        public String getName() {
            return "first filtered out, subsequent pass";
        }

        @Override
        public int getPriority() {
            return 0;
        }
    };
    final MessageFilterChainProcessor filterTest = new MessageFilterChainProcessor(new MetricRegistry(), Collections.singleton(filterOnlyFirst), journal, serverStatus);
    Message filteredoutMessage = new Message("filtered out", "source", Tools.nowUTC());
    filteredoutMessage.setJournalOffset(1);
    Message unfilteredMessage = new Message("filtered out", "source", Tools.nowUTC());
    final Messages messages1 = filterTest.process(filteredoutMessage);
    final Messages messages2 = filterTest.process(unfilteredMessage);
    Assert.assertTrue(filteredoutMessage.getFilterOut());
    Assert.assertFalse(unfilteredMessage.getFilterOut());
    Assert.assertEquals(0, Iterables.size(messages1));
    Assert.assertEquals(1, Iterables.size(messages2));
}
Also used : Messages(org.graylog2.plugin.Messages) Message(org.graylog2.plugin.Message) MetricRegistry(com.codahale.metrics.MetricRegistry) MessageFilter(org.graylog2.plugin.filters.MessageFilter) Test(org.junit.Test)

Example 10 with Journal

use of org.graylog2.shared.journal.Journal in project graylog2-server by Graylog2.

the class MessageFilterChainProcessorTest method testAllFiltersAreBeingRun.

@Test
public void testAllFiltersAreBeingRun() {
    final DummyFilter first = new DummyFilter(10);
    final DummyFilter second = new DummyFilter(20);
    final DummyFilter third = new DummyFilter(30);
    final Set<MessageFilter> filters = ImmutableSet.of(first, second, third);
    final MessageFilterChainProcessor processor = new MessageFilterChainProcessor(new MetricRegistry(), filters, journal, serverStatus);
    final Message message = new Message("message", "source", new DateTime(2016, 1, 1, 0, 0, DateTimeZone.UTC));
    final Message result = Iterables.getFirst(processor.process(message), null);
    assertThat(result).isNotNull();
    assertThat(result.getFields()).containsKeys("prio-10", "prio-20", "prio-30");
}
Also used : Message(org.graylog2.plugin.Message) MetricRegistry(com.codahale.metrics.MetricRegistry) MessageFilter(org.graylog2.plugin.filters.MessageFilter) DateTime(org.joda.time.DateTime) Test(org.junit.Test)

Aggregations

MetricRegistry (com.codahale.metrics.MetricRegistry)5 Test (org.junit.Test)5 Message (org.graylog2.plugin.Message)4 MessageFilter (org.graylog2.plugin.filters.MessageFilter)4 DateTime (org.joda.time.DateTime)3 Timer (com.codahale.metrics.Timer)2 Timed (com.codahale.metrics.annotation.Timed)2 ApiOperation (io.swagger.annotations.ApiOperation)2 IOException (java.io.IOException)2 ArrayList (java.util.ArrayList)2 GET (javax.ws.rs.GET)2 LogSegment (kafka.log.LogSegment)2 RequiresPermissions (org.apache.shiro.authz.annotation.RequiresPermissions)2 Notification (org.graylog2.notifications.Notification)2 Messages (org.graylog2.plugin.Messages)2 ThrottleState (org.graylog2.plugin.ThrottleState)2 RawMessage (org.graylog2.plugin.journal.RawMessage)2 HdrTimer (org.graylog2.shared.metrics.HdrTimer)2 JsonNode (com.fasterxml.jackson.databind.JsonNode)1 Size (com.github.joschi.jadconfig.util.Size)1